ch3cke的小站

长夜将至,我从今日起开始守望

0%

练习题(1)

几天做了几道逆向题,简单记录一下解题思路和过程

Petition

程序链接这个题目来自某次比赛的一个逆向题,比较有意思的是这个题目存在一些小小的问题,存在一些小小的反调试,题目中的数据操作大部分是异或操作,逆向起来直接反汇编无法分析程序,只能看汇编。首先用IDA打开程序:

分析这个程序,可得这个程序的检验的方式是逐字符检验,一旦有某个字符错误,就会直接推出,根据题目的难度和数据操作的方式,现有两个解决方案:

  • Pin 插桩

  • 直接逆向

直接逆向

这个需要分析一下程序的数据操作流程,根据动态调试可知,这个程序的流程是:

  1. 首先是将输入的数据与一个大数进行异或,取其最后八位

  2. 再将这个最后八位与函数里面的两个数据进行异或

  3. 最后判断异或的结果是是否为0,为0则继续判断,否则退出
    以此函数为例,使用0xcc84881e的最低位 0x1e与后面的0x3e 0x46进行异或,可得flag第一位,跟进函数sub_119c:
    即可得到flag第二个字符的检测:
    一直遍历可得flag:
    flag{96c69646-8184-4363-8de9-73f7398066c1}

Pin 插桩

待补充。。。。。

easy-crypto

程序链接这个程序是一个PE可执行程序,可以本地动态调试,存在一定的花指令的,无法反汇编,需要将程序进行一些patch

花指令修复

找到主函数地址0x401660,发现未被实现为函数,手动设置为函数,报错:.text:004016F4: The function has undefined instruction/data at the specified address.
在地址0x4016f4地址存在问题:
可知0xede9无法被识别, 将其patch为nop。程序存在多个同样的花指令,将其全部patch为nop后,就可以将其设置为函数,并可以进行反编译。

函数分析

  • main位置变换

  • base64:

  • 使用IDA插件findcrypt插件,查找加密算法,发现存在一个XTEA加密算法:

  • 检测结果
    总结一下,函数通过一种未知变换,再进行XTEA加密后,最后进行base64加密,与密文进行比较。
    python解密脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
table  = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/'

enc = '248n4EJTTTEaceRT8kL8EAgoxIaKfvamSsOfg5EXusE'

flag = ''

def to(s):
dd = ''
for i in s:
dd += ('{:02x}'.format(i))
return dd

if __name__ == '__main__':
for i in enc:
flag += ('{:06b}'.format(table.find(i)))
print(flag)
flags = []
for i in range(0,len(flag), 8):
flags.append(int(flag[i:i+8],2))
for i in range(0, len(flags), 4):
print(to(flags[i:i+4:][::-1]))

XTEA解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>

void decrypt_xtea(unsigned int num_rounds, uint32_t* v, uint32_t* k) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
for (i=0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
}
v[0]=v0; v[1]=v1;
}

int main(){
uint32_t v[2] = {0x12174208, 0x7adf778b};
uint32_t v1[2] = {0x77ed300a, 0xa2c84b21};
uint32_t v2[2] = {0xc2861844, 0x96f23dae};
uint32_t v3[2] = {0x408fccd9, 0xca793b5a};
//uint32_t v[2] = {0x33333333, 0x34343434};
//uint32_t v[2] = {0xa5884ef3, 0x6ea37aa2};
uint32_t k[4] = {0x6a,0x78,0x73,0x7a};
decrypt_xtea(32, v, k);
decrypt_xtea(32, v1, k);
decrypt_xtea(32, v2, k);
decrypt_xtea(32, v3, k);
printf("%lx, %lx,", v[0],v[1]);
printf("%lx, %lx,", v1[0],v1[1]);
printf("%lx, %lx,", v2[0],v2[1]);
printf("%lx, %lx,", v3[0],v3[1]);
}

由于变换是类似交换的操作,是可逆的,所以将解密的数据直接输入,就可以在动态调试看到flag

flag{f1bf4dfbfc4dc9df45b5da87d552ed02}

before-main

这是最简单的题目,难点是无法反编译,存在花指令,只能看汇编,但只是一个简单的异或

花指令分析


还是存在几个花指令,nop掉之后,还是存在栈不平衡,但是只有存在异或操作
异或的密文为0x00403138处的数据:

key具有迷惑性,为dword_404018处的数据,但是在0x401075处进行修改了


key最终为:[122, 115, 120, 106]

1
2
3
4
5
6
7
enc = [0x1C, 0x1F, 0x19, 0x0D, 0x01, 0x19, 0x00, 0x5F, 0x00, 0x2C, 0x09, 0x1D, 0x1F, 0x2C, 0x11, 0x58, 0x49, 0x12, 0x0B, 0x17]
key = [122, 115, 120, 106]
s = ''
for i in range(0, len(enc)):
s += (chr(enc[i]^key[i%4]))
print(flag)
# flag{jx5z_qwe_i23as}

flag{jx5z_qwe_i23as}