[CISCN 2023 初赛]babyRE
给了个xml,notpad不好看直接放到edge里看看

发现一个假flag,和很可疑的字符串
上面好像是创建了一个数组,然后再往上是有一个遍历异或

不能硬看吧哥T T ,在我试图把img解密的时候看到了这个头

进到snap网站发现可以直接导入

找到关键逻辑,一个逐位异或,左边丢gpt得到数组

a = [102, 10, 13, 6, 28, 74, 3, 1, 3, 7, 85, 0, 4, 75, 20, 92, 92,
8, 28,25, 81, 83, 7, 28, 76, 88, 9, 0, 29, 73, 0, 86, 4, 87, 87, 82, 84, 85, 4, 85, 87, 30]
flag = "" + chr(102)
for i in range(1,len(a)):
a[i] = a[i] ^ a[i - 1]
flag += chr(a[i])
print(flag)
#flag{12307bbf-9e91-4e61-a900-dd26a6d0ea4c}
[CISCN 2023 初赛]ezbyte
直接运行是将我们的输入回显回来,扔ida
main函数有很显眼的输入函数,用finger还原下函数可以看到就一个函数不是标准函数,对flag有一个基本的检测


flag{111111111111111111111111111111113861} 扔进去调起来
在doASyncWork看到有很显眼的throw抛出异常,进expection估计是主逻辑了,进去又抛异常,继续跟到这个位置发现关键的字符串 “yes”,直接patch一下,发现改为jnz后是有回显yes的

r13经过xor为0,所以要求r12也是0才能跳转,但是r12并没有看到赋值,结合题目字节码分析(要是没见过这个东西,真的做不了一点)
知识点
在函数抛出异常的时候会向上(caller)一层层寻找有无catch解决异常,在不断还原之前函数环境的时候,需要不断从栈上将当时的环境还原——栈展开(stack unwind),早期的负责还原环境的ABI DWARF,只支持esp加减offset操作取值以及赋值,这很显然已经不能满足现在的情况,所以在DWARF 3的时候推出了DWARF Expression,来方便caller的环境还原
DWARF Expression类似于在栈上的一个小型虚拟机,可以执行类似汇编的指令来操作栈上的数据,但是不能向内存中写入数据,可以将操作后的数据放到栈顶,这就使得攻击者可以将恶意代码按照语法转化后,再通过修改寄存器的值将数据插入到这些字节码中并在抛出异常后执行
可以在Linux上通过下面的指令将文件的信息写到文件里,搜索目标寄存器就能找到相应的数据
DWARF Debugging Information Format Version 5 (dwarfstd.org) 附官方文档
然后对照官方的文档就像看汇编一样
readelf -wf t1 > out.txt
/* DW_CFA_val_expression: r12 (r12) (DW_OP_constu: 2616514329260088143; DW_OP_constu: 1237891274917891239; DW_OP_constu: 1892739; DW_OP_breg12 (r12): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_constu: 8502251781212277489; DW_OP_constu: 1209847170981118947; DW_OP_constu: 8971237; DW_OP_breg13 (r13): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_or; DW_OP_constu: 2451795628338718684; DW_OP_constu: 1098791727398412397; DW_OP_constu: 1512312; DW_OP_breg14 (r14): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_or; DW_OP_constu: 8722213363631027234; DW_OP_constu: 1890878197237214971; DW_OP_constu: 9123704; DW_OP_breg15 (r15): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_or) */
回归主线
目标是r12最后的值为0 ,找个txt模拟下栈就能得到flag了
(flag1 – 1892739) ^ 1237891274917891239 ^ 2616514329260088143 == 0剩下的同理
DW_OP_constu: 2616514329260088143;
DW_OP_constu: 1237891274917891239;
DW_OP_constu: 1892739;
DW_OP_breg12 (r12): 0;
DW_OP_plus;
DW_OP_xor;
DW_OP_xor;
//(flag1 - 1892739) ^ 1237891274917891239 ^ 2616514329260088143 == 0
DW_OP_constu: 8502251781212277489;
DW_OP_constu: 1209847170981118947;
DW_OP_constu: 8971237;
DW_OP_breg13 (r13): 0;
DW_OP_plus;
DW_OP_xor;
DW_OP_xor;
DW_OP_or;
DW_OP_constu: 2451795628338718684;
DW_OP_constu: 1098791727398412397;
DW_OP_constu: 1512312;
DW_OP_breg14 (r14): 0;
DW_OP_plus;
DW_OP_xor;
DW_OP_xor;
DW_OP_or;
DW_OP_constu: 8722213363631027234;
DW_OP_constu: 1890878197237214971;
DW_OP_constu: 9123704;
DW_OP_breg15 (r15): 0;
DW_OP_plus;
DW_OP_xor;
DW_OP_xor;
DW_OP_or

#flag{c69d13ca-96ca-49e4-e07e-5bfe906e3861}
[CISCN 2023 初赛]moveAside
扔进ida发现是movfuscator混淆,之前比赛是见过的,但是当时是直接明文比对没有任何加密
看函数表是调用了strcmp函数以及srand,time。丸辣!不会是srand(time(0))吧,那这一坨mov看个蛋的逻辑啊

运行起来是将输入回显回来的,直接在strcmp下断调试,在输入之前这个函数也是一直被调用,不知道在干嘛,直接来到函数输入的位置
也是在栈上找到了我们的输入,还有一段可疑的字符串


mov虽然在理论上可以实现所有的操作,但是却无法实现很便捷的函数,所以需要多次调用strcmp来一次次的对我们的输入进行检验,在下面的栈上可以看到每次比较的数据

继续走就会发现如果有一次不一样就会进singal异常里面,感觉可以直接写个爆破啊,每次到比较的时候将数据get出来,将十六进制数据table表遍历,每次运行到比较的时候如果一样就+=到flag里面
理论存在,实践不了一点,哥们不会写这脚本啊,在程序运行中获得程序内存相应的数据这种API没见过呀,挖个坑先看有没有机会填这个坑 T_T
去看了下大佬的wp,说是通过密文可以看出有映射关系 “\” -> “-” 我确实没这么想过

通过爆破映射表得到flag,呃呃…..
那我直接通过不断修该strcmp的数据一个个把映射表提取出来不就行了,说干就干(真枯燥不是我说要重复这个操作16次)
unk_8600154 是input encode后的数据 unk_860014C 是密文相应的数据
然后就得到了box,得到flag
a = [0x67, 0x9D, 0x60, 0x66, 0x8A, 0x56, 0x49, 0x50, 0x65, 0x65, 0x60, 0x55, 0x64, 0x5C, 0x65, 0x48, 0x50, 0x51, 0x5C, 0x55, 0x67, 0x51, 0x57, 0x5C, 0x49, 0x67, 0x54, 0x63, 0x5C, 0x54, 0x62, 0x52, 0x56, 0x54, 0x54, 0x50, 0x49, 0x53, 0x52, 0x52, 0x56, 0x8C]
table = "flag{0123456789abcde}-"
box = [0x67, 0x9D, 0x60, 0x66, 0x8A,0x51,0x50,0x53 ,0x52 ,0x55 ,0x54 ,0x57 ,0x56 ,0x49 ,0x48 ,0x60 ,0x63 ,0x62,0x65,0x64,0x8c,0x5c]
flag = ""
for i in a:
for j in range(len(box)):
if box[j] == i:
flag += table[j]
break
print(flag)
#flag{781dda4e-d910-4f06-8f5b-5c3755182337}
还剩两题改天再来补上