混淆技术和PE文件基本知识
基本花指令的识别和去除
PE文件结构
查壳发现是16位可执行文件,有点不对劲
在010中发现本应指向PE头地址的3C位置值为0000
PE头位于E0位置
将3C位置改为E0再次分析
发现是32位程序无壳
拖进ida中静态分析
有花指令影响函数分析
Push eax
Xor eax,eax
Test eax,eax
eax与自己异或后再与自己比较zf标志位的值恒为1
造成jz跳转永远执行jnz跳转永不执行
可以看到jz跳转到locret_4158C6位置
4158BC到4158C6中间的代码永远不会被执行,正是这些代码影响了函数分析
只需要将4158BC到4158C6中间的代码用90代替即可实现去除花指令
利用ida快捷键u和快捷键p重新分析函数
可以发现这部分代码能被正常分析了
继续向下分析
在4159B9位置发现同样的互补条件跳转混淆
通用zf标志位为1 jz跳转执行
可以看出jz跳转到下面的jmp后每次都只执行跳转命令(相同颜色为跳转执行位置和跳转目标位置)
直到loc_4159CF才开始正常执行指令
所以从jz开始到loc_4159CF都是花指令
将花指令nop后再次分析代码
可以看出_main_0已经被分析出来了
F5查看伪代码
分析代码可以看出sub_4113CF应该是主要加密函数
框内代码明显看出是由call&ret构造花指令
将41179B到4117A7间的数据nop掉再重新分析代码
花指令去除完毕
分析主函数代码:
将输入的字符串每8个一组和v8一起传入sub_4113CF进行加密
然后将密文与v9进行对比
根据传参和sub_4113CF中代码特征可以看出为xtea加密
网上找脚本并解密:
#include<stdio.h>
#include <iostream>
using namespace std;
void decrypt_xtea(uint32_t num_rounds, uint32_t v[2], uint32_t const key[4]) {
uint32_t 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 + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}
int main()
{
char data[] = { 0x69,0xFFFFFF9B,0xFFFFFFB5,0xFFFFFF83,0xFFFFFFD6,0xFFFFFFDF,0xFFFFFFAD,0x68,0x18,0xFFFFFFE4,0x68,0x4C,0x3E,0x53,0x1C,0xFFFFFF87,0x7D };
uint32_t key[] = { 0x12345678,0x23456789,0x33456789,0x44456789 };
for (size_t i = 0; i < 2; i++) decrypt_xtea(32, (uint32_t*)&data[i * 8], key);
for (int i = 0; i < sizeof(data); i++)
printf("%c", data[i]);
}
得到flag: flag{happy_ctf!!}