pwn70
目录
题目
预计时间
2h
题目分析及截图
我们首先checksec看看一下程序的保护机制
1 | yyh@yyh:~/pwn70$ checksec ./pwn |
可以看到程序只开启了canary
我们打开Ida看一下程序的反编译出来的代码
main函数
1 | .text:0000000000400A68 main proc near ; DATA XREF: _start+1D↑o |
我解释一下这个汇编代码
1
2
3.text:0000000000400A68 push rbp
.text:0000000000400A69 mov rbp, rsp
.text:0000000000400A6C add rsp, 0FFFFFFFFFFFFFF80h分配一个70h的栈帧
1
2mov [rbp+var_74], edi ; argc
mov [rbp+var_80], rsi ; argv保存参数
1
2mov rax, fs:28h
mov [rbp+var_8], rax保存canary
1
2call init
call set_secommp调用 init 和 seccomp函数。
seccomp是沙箱的标志,我们一会要使用seccomp-tools工具来看哪些系统调用可执行
1
2
3
4lea rax, [rbp+s]
mov esi, 0x68 ; 104 字节
mov rdi, rax
call _bzero清零0x68字节
1
2call logo
puts("Welcome,tell me your name:")打印logo,输出欢迎语
1
2
3
4
5lea rax, [rbp+s]
mov edx, 0x64 ; nbytes = 100
mov rsi, rax ; buf
mov edi, 0 ; fd = stdin
call read调用read函数,从stdin中最多读取0x64字节,read的返回值在eax中
1
2
3sub eax, 1
cdqe
mov [rbp+rax+s], 0将最后一个字节改成
\x00,即c字符串结尾1
2
3
4
5lea rax, [rbp+s]
mov rdi, rax
call is_printable
test eax, eax
jz short loc_400AFE检查是否全是printable字符
is_printable 函数
1 | __int64 __fastcall is_printable(const char *a1) |
先获取字符串长度,循环遍历每一个字符
由于在汇编中看见了沙箱函数,所以这时,我们需要使用seccomp-tools dump ./pwn命令去看一下程序的可执行系统调用
1 | yyh@yyh:~/pwn70$ seccomp-tools dump ./pwn |
除了execve都可以进行系统调用,那我们及就可以使用ORW或者直接cat
在之前,我们也写过一个这样的题目,都是对shellcode中的每一位字符进行限制,但是在当时我们是使用/x00来绕过的,但是,/x00的含义在不同位置并不同
- 在
is_printable函数中,我们输入的相当于是c语言中/x00的意思,也就是字符串结束符的意思 - 在发送payload时就是汇编语言中的意思,但是
/x00是不能单独出现的,需要构成一条完整的汇编命令,在这里我们可以使用程序中有的指令/x00/xc0,当然你也可以直接自己构造
其实到这里很简单了,我们直接写入shellcode就好了(需要加/x00进行绕过),因为这道题不涉及覆盖返回地址,我们不需要去管金丝雀值
exp如下(cat写法)
1 | from pwn import * |
- 因为flag在文件/flag里,所以这里我们就使用cat,当然也可以使用ORW
\x00\xc0是ADD AL,AL的意思,是程序中出现的代码