VNCTF_2022
VN2022
cm狗
用jadx软件载入这个apk文件
判断flag的函数
判断的函数
loadDexClass()的这个函数
这里copyfile了一个dex的文件,这里copyFile()函数里面应该还有一系列的操作,一系列操作的结果最后写入了创建的一个文件里面
找到这个文件,并且找到这个函数
该函数的详情
主要的代码
注意这个地方是每次取1024出来,外层有个while(true)的循环的操作
得到的这个文件名称是 classes.dex
对文件进行操作的脚本:
1 | v0 = 'vn2022' |
将得到的这个文件命名为class.dex,这是一个dex文件,首先使用dex2jar 将 dex文件转变成jar文件,然后使用jd-gui打开这个得到的jar文件,注意使用dex2jar得到jar文件的时候,需要将dex文件放入到dex2jar的文件夹目录之下
得到的这个文件之中
加密函数 (xxtea加密)
在hcheck这个函数之中,首先给了一堆数字,然后将输入的flag以及xxtea的密钥输入,对输入进行加密,加密的结果就是上面定义的一系列数值
去网上找一个xxtea解密的脚本
1 | #include <stdio.h> |
所以最后的flag 是 VNCTF{93ee7688-f216-42cb-a5c2-191ff4e412ba}
BabyMaze
这道题如果直接使用employee6 解pyc得到代码是不行的,因为在这个代码里面有花指令,
方法一:直接使用pycda中的得到bytecode的底层的代码
看见迷宫,拼一下迷宫,按照w代表向上走,s代表向下走,a代表向左走,d代表向右走的方式走迷宫
python的pyc文件的反编译pycdc和pycdas这两个文件,pycdc反编译为python的代码,pycdas这个文件会将pyc文件编译成字节码的形式 pyc反编译
1 | /* Bytecode object */ |
得到:走出的迷宫的结果
ssssddssaassddddwwwwddwwddddddwwddddddssddwwddddddddssssaawwaassaassaassddssaassaawwwwwwaaaaaaaassaassddddwwddssddssssaassddssssaaaaaawwddwwaawwwwaassssssssssssddddssddssddddddddwwaaaaaawwwwddssddwwwwwwwwddssddssssssssddddss
将上面的解md5(32小写)得到最后的结果 VNCTF{801f190737434100e7d2790bd5b0732e}
1 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 |
VNCTF{801f190737434100e7d2790bd5b0732e}
时空飞行
运行一下这个程序,因为不能直接运行,所以使用IDA调试运行,所以现在我们需要找到日期和符来歌(根据运行之中的提示语句得到)
变化之后的日期:
1 | 0FD07C452h, 0EC90A488h, 68D33CD1h, 96F64587h |
对输入的日期进行加密的过程
v5[v3] = sub_401A3B(v5[i + 3] ^ v5[i + 2] ^ (unsigned int)v5[i + 1] ^ dword_405040[i]) ^ v4;
1 | v5[4] = sub_401A3B(v5[3] ^ v5[2] ^ (unsigned int)v5[1] ^ dword_405040[0]) ^ v5[0]; |
sub_401A3B()这个函数的作用
a1和a1向左移13位的结果和a1向右移9位的结果做异或运算,
逆向分析的脚本:
1 | #include <stdio.h> |
将得到的日期放入之后,就要进行符来歌的输入
最后需要对比的元素是
1 | 0x1ebe,0x1e8e,0x1e44,0x1e39,0x1e5b,0x1e8,0x1e36,0x1e8f,0x1edd,0x1e5e,0x1e94,0x1eb5,0x1e1,0x1e70,0x1eab,0x1e63,0x1ebb,0x1e72,0x1e50,0x1e13,0x1e5d,0x1e25,0x1e16,0x1e78 |
在上面函数 之中对这个数组中的元素做了一定的运算,下面得到的就是运算加密之后的数组
所以需要比较的数组是
1 | 0x25,0x15,0xdf,0xa2,0xc0,0x93,0xad,0x14,0x46,0xc5,0xf,0x2e,0x9a,0xeb,0x30,0xf8,0x20,0xe9,0xcb,0x88,0xc6,0xbe,0x8d,0xe3 |
用爆破的方式得到上面的解,发现这里某些会有多个解所以需要使用递归的方式,深度优先算法解得所有的解
1 | obj = [ 0x25,0x15,0xdf,0xa2,0xc0,0x93,0xad,0x14,0x46,0xc5,0xf,0x2e,0x9a,0xeb,0x30,0xf8,0x20,0xe9,0xcb,0x88,0xc6,0xbe,0x8d,0xe3] |
通过这个我们可以获得 a1[60] a1[61] a1[62] a1[63] a1[64] a1[65] 5个数
对输入的每32个字节的操作:将32位数 F1F1 F2F2 F3F3 F4F4 排列为 F4F4 F3F3 F2F2 F1F1
将所有输入的字符进行上面的运算,然后重新赋值给a1 则可以知道数组之中有6个元素
然后就需要进行一系列的运算,
当v5不是6的倍数的时候
当i不是6的倍数的时候:v5[7] = v5[1]^v5[6] v5[i] = v5[i-6] ^ v5[i-1]
当i是6的倍数的时候:v5[i] = v5[i-6] ^ T(v5[i-1],v3) v3代表的是第几个6的倍数
T函数的讲解:
其中的第一个函数:将a1分解成了4个元素的数组0x F0F0 F1F1 F2F2 F3F3
其中的第二个函数:将数组中的元素循环右移一位 ;例如 a=[a0,a1,a2,a3] 转化成 a=[a1,a2,a3,a0]
[F3F3,F2F2,F1F1,F0F0] [F2F2,F1F1,F0F0,F3F3]
其中第三个函数:整合上面的数组之中的元素 0x F3F3 F0F0 F1F1 F2F2
所以这个函数的作用是 将 0x F0F0 F1F1 F2F2 F3F3 转化成 0x F3F3 F0F0 F1F1 F2F2 循环左移动了8位 然后再和对应那个6的倍数作为脚标找到数组对应的元素
作为索引对象的数组是:
1 | [0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, |
每组得到了6个数字,将这六个元素作为66个元素之中的后六位元素
逆向:
当i不是6的倍数时: v5[i-6] = v5[i]^v5[i-1]
当i是6的倍数时: v5[i-6] = v5[i]^ T(v5[i-1],v3) # v3 = i%6 T是将数循环左移动了8位,再和对应的数字进行异或运算
逆向得到的66个元素的前6个元素,将前6个元素转化为字符输出
所有运算的脚本:
1 | obj = [ 0x25,0x15,0xdf,0xa2,0xc0,0x93,0xad,0x14,0x46,0xc5,0xf,0x2e,0x9a,0xeb,0x30,0xf8,0x20,0xe9,0xcb,0x88,0xc6,0xbe,0x8d,0xe3] |
在所有的输出之中找到flag VNCTF{TimeFlightMachine}
cmgo!
将这个exe文件拖入ida之中,从函数名称的窗口之中就可以看到这里进行了程序的无符号化,使得函数的名称不能够直观的得到,所以函数的入口难以找到,无符号golang逆向技巧,使用IDAGolangHelper这一脚本,打开脚本文件(文件-脚本文件)找到这个脚本文件夹,选中rename function之后选择go版本,所以将这个exe拖进IDA7.6之中,找到程序入口main.main
找到初始化虚拟机的地方和opcode
第二个函数 mov
第三个函数 mov
第四个函数 mov
第五个函数 push
第六个函数 和push类似的样子
第七个函数 pop
第八个函数 add
第九个函数 sub
第十个函数 div
第十一个函数 mul
第十二个函数 xor
第十三个函数 jmp
第十四个函数 jmp(多了一个判断条件)当等于的时候跳转
第十五个函数 jnp
第十六个函数 jlp 当小于的时候跳转
第十七个函数 jhp 当大于的时候跳转
第十八个函数 scanf
第十九个函数 print
第二十个函数 quit
初始化虚拟机并且载入opcode之后,要运行这个虚拟机,所以查看虚拟机的运行的函数,用流程图的方式查看函数的逻辑,找到逻辑之中的循环,找到其中的关键代码
进行动调得到函数的对应关系,动态调试得到的对应关系,
跟踪到[rbx+rdi*8+1008h]这个里面,通过按D将db的数据转化成dq
通过他们的顺序,就能知道code 和 函数的对应关系
opcode的 0-16对应函数1-17
97 98 99对应函数18 19 20
将opcode得到
1 | mov r0 0X57 |
网上的TEA的加密代码:
1 | void encrypt (uint32_t v[2], const uint32_t k[4]) { |
网上的TEA的解密代码:
1 | void decrypt (uint32_t v[2], const uint32_t k[4]) { |
这道题目之中的TEA解密的代码:
1 | #include <bits/stdc++.h> |