第二届广东省大学生网络攻防大赛 simple_re
流程总结:(思路原文出自 JANlittle 师傅)
程序将关键函数以对象元素的形式存在对象里,然后在申请内存中搭配指针间接调用,关键是把内存空间中对应位置的函数和变量用流程图梳理清除。
sub_140002110 有反调试,主要是 IsDebuggerPresent 和获取 ThreadContext 并检测是否有硬件断点。
加密流程为先打乱每个字节的比特顺序,其实就是把比特串倒过来;然后利用打乱比特顺序的前 4 字节输入 SMC 解密一段代码,并开一个线程检测 SMC 解密后的代码段是否有 0xcc,有的话说明前 4 字节输入错误;之后调用上述代码段进行魔改 XTEA 加密。
.
.
下载程序,照例扔入 exeinfope 中查看信息:
.
.
64 位 exe 文件,无壳,照例扔入 IDA64 中查看伪代码,有 main 函数看 main 函数:
.
.
第一部分是输入字符比特流倒序,接下来我们看第二部分:
.
.
第二部分的 SMC 解密处后面再说,因为要用到第三部分的数据,所以卡住不要紧张,说不定答案在后面呢。现在我们来看第三部分:
.
.
第三部分——用 Str1 的前 4 个字节生成 SMC 代码:
b=[ 0x27, 0x44, 0x7F, 0xEB, 0x3A, 0x8F, 0x1A, 0x2E, 0xFB, 0x41,
0xE6, 0x46, 0xFB, 0x59, 0xEE, 0x42, 0xFB, 0x49, 0xD6, 0x46,
0xF9, 0x49, 0xEE, 0x85, 0x72, 0x85, 0xB3, 0xF6, 0x3A, 0x87,
0xB3, 0x16, 0xF9, 0x4C, 0xF2, 0x87, 0x37, 0xF8, 0x31, 0x4B,
0x82, 0x0C, 0xF6, 0x0E, 0x72, 0xCB, 0xB3, 0xE2, 0x0D, 0xA0,
0x9C, 0x89, 0xB5, 0x49, 0x0A, 0x0E, 0x72, 0x0C, 0xF6, 0x85,
0x37, 0xF0, 0xCD, 0x4B, 0x62, 0x03, 0x75, 0x8A, 0x72, 0x0C,
0xF6, 0x85, 0x37, 0xF8, 0x7B, 0x1A, 0xB7, 0x0C, 0xF6, 0x0E,
0x72, 0x87, 0xB3, 0xFA, 0xB3, 0xE4, 0xF0, 0x3F, 0xB0, 0x87,
0xB3, 0xFA, 0x73, 0xCE, 0x7D, 0x4B, 0x82, 0x8F, 0x16, 0x0D,
0x3A, 0x81, 0xFA, 0x8B, 0x72, 0x0C, 0xF6, 0x0E, 0x3A, 0x87,
0xB3, 0x2E, 0x3A, 0x0D, 0x3E, 0x85, 0x7A, 0x87, 0xB3, 0xFE,
0x73, 0xC4, 0xC7, 0xDE, 0x73, 0x49, 0x0E, 0x85, 0x37, 0xE0,
0xF7, 0x4B, 0x82, 0x87, 0xB3, 0xF6, 0xFF, 0x18, 0x33, 0x0E,
0x72, 0x0C, 0xF6, 0x85, 0x37, 0xF4, 0x37, 0xE6, 0x74, 0x3D,
0x34, 0x85, 0x37, 0xF4, 0xF7, 0xCC, 0xF9, 0x49, 0x06, 0xCF,
0x9A, 0x07, 0x7F, 0xCE, 0xF1, 0xEC, 0xF5, 0x46, 0xFF, 0x00,
0x73, 0x0E, 0x72, 0x0C, 0xF6, 0x46, 0xF9, 0x49, 0xD6, 0x46,
0x73, 0xC4, 0x7D, 0x06, 0xF9, 0x49, 0x06, 0x0F, 0xBA, 0x3D,
0x26, 0x0F, 0x37, 0xF8, 0x75, 0x4B, 0x8E, 0x0D, 0x1F, 0x7E,
0x8D, 0xF3, 0x09, 0x46, 0xF9, 0x49, 0xEE, 0x85, 0x27, 0xF4,
0x7F, 0x1E, 0x3A, 0x87, 0xB3, 0x16, 0x3A, 0x8F, 0x36, 0x0A,
0xF9, 0x59, 0x02, 0x87, 0x62, 0x9C, 0xBE, 0x8D, 0xB6, 0x2C,
0xAB, 0xCD]
Str1=[0x72, 0x0C, 0xF6, 0x0E]
address=0x140042000
for i in range(232):
patch_byte(address+i,Str1[i%4]^b[i])
print("success")
.
.
最后梳理流程,写解密代码:(代码出自 JANlittle 师傅)**
#include <stdio.h>
#include <stdint.h>
void decipher(unsigned int num_rounds,uint32_t v[2],uint32_t const key[4]){
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x78955381, sum = delta * -num_rounds;
for(i = 0; i < num_rounds; i++){
v1 -= (((v0 << 3) ^ (v0 >> 6))+v0) ^ (sum + key[(sum >> 11) & 3]);
sum += delta;
v0 -= (((v1 << 3) ^ (v1 >> 6)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}
uint8_t rebits(uint8_t n)
{
uint8_t count = 0;
for(int i = 0; i < 8; i++)
{
count = count *2 + n % 2;
n /= 2;
}
return count;
}
int main(){
uint8_t enc[]={0x72, 0x0C, 0xF6, 0x0E, 0x8C, 0x69, 0x23, 0x69, 0x59, 0xA8, 0x06, 0xEF, 0x2A, 0x1A, 0x56, 0xB6, 0x96, 0xAC, 0xEE, 0x92,0x5C, 0xF2, 0xED, 0x0A, 0x5F, 0x36, 0x8E, 0x41, 0xA6, 0x36, 0x86, 0x72, 0x56, 0xD2, 0x54, 0xC2, 0x00, 0xC8, 0xA8, 0x00};
uint8_t key1[33] = "Welcome to the g";
uint8_t key2[32] = "ame!\nYour key: ";
unsigned int r=12;
decipher(r,(uint32_t *)(enc+4),(const uint32_t *)key1);
decipher(r,(uint32_t *)(enc+20),(const uint32_t *)key2);
for(int i =0; i < 40; i++)
enc[i]=rebits(enc[i]);
printf("%s",enc);
return 0;
}
.
.
.
.
参考博客:
http://blog.leanote.com/post/xp0int/2022-%E5%B9%BF%E4%B8%9C%E7%9C%81%E5%A4%A7%E5%AD%A6%E7%94%9F%E7%BD%91%E7%BB%9C%E6%94%BB%E9%98%B2%E5%A4%A7%E8%B5%9B%E9%83%A8%E5%88%86#p-4
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)