考点:魔改upx壳,vm,魔改rc4
用脱壳机脱壳失败,报错IOexceptationbadseek2.那么大概就是修改了某个地方的特征码。但是很可惜当时不知道这个知识点。后来知道是改了最后的四个字节,只需要把最后四个字节改成0xf4,00,00,00就能用脱壳机脱壳。
for ( i = 0; i <= 3; ++i )
*(&a1->_eax + i) = 0;
a1->_eip = &unk_4020;
LODWORD(a1->eflag) = 0;
for ( j = 0; j <= 7; ++j )
{
LOBYTE(a1->functable[j].opcode) = j - 16;
a1->functable[j].funcs = *(&off_41A0 + j); //绑定函数
}
s = malloc(0x300uLL);
memset(s, 0, 8uLL);
v1 = s + 544;
result = qword_4140;
v3 = qword_4148;
*(s + 68) = qword_4140;
*(v1 + 1) = v3;
return result;
}
这个函数为vm虚拟机的初始化代码,包含了一些寄存器,指向操作码opcode的eip,标志位,以及调度器所调用的一些handle函数等。将a1的类型更改为自定义的结构体类型可以好看一点。
#include<stdio.h>
unsigned char opcode[] =
{
0xF0, 0xE0, 0x02, 0x00, 0xF0, 0xE0, 0x00, 0xE0, 0x02, 0xF0,
0xE1, 0xE0, 0x02, 0xE0, 0x02, 0xF0, 0xE0, 0x01, 0x10, 0xF2,
0xE0, 0x00, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0x20, 0x02, 0xF0,
0xE0, 0x00, 0xE1, 0xE0, 0x00, 0xF0, 0xE0, 0x01, 0xE0, 0x02,
0xF1, 0xE0, 0x01, 0x00, 0x01, 0xF0, 0xE1, 0xE0, 0x01, 0xE0,
0x00, 0xF3, 0xE0, 0x02, 0xF6, 0xE0, 0x02, 0x00, 0x01, 0xF7,
0x04, 0xF0, 0xE0, 0x02, 0x00, 0xF0, 0xE0, 0x03, 0x00, 0xF0,
0xE0, 0x00, 0xE1, 0xE0, 0x02, 0xF1, 0xE0, 0x03, 0xE0, 0x00,
0xF0, 0xE0, 0x00, 0xE1, 0x02, 0xF1, 0xE0, 0x00, 0x00, 0x01,
0xF0, 0xE0, 0x00, 0xE1, 0xE0, 0x00, 0xF1, 0xE0, 0x03, 0xE0,
0x00, 0xF2, 0xE0, 0x03, 0x00, 0x01, 0xF0, 0xE0, 0x00, 0xE1,
0xE0, 0x02, 0xF0, 0xE0, 0x01, 0xE1, 0xE0, 0x03, 0xF0, 0xE1,
0xE0, 0x03, 0xE0, 0x00, 0xF0, 0xE1, 0xE0, 0x02, 0xE0, 0x01,
0xF3, 0xE0, 0x02, 0xF6, 0xE0, 0x02, 0x00, 0x01, 0xF7, 0x45,
0xF0, 0xE0, 0x02, 0x00, 0xF0, 0xE0, 0x03, 0x00, 0xF3, 0xE0,
0x02, 0xF2, 0xE0, 0x02, 0x00, 0x01, 0xF0, 0xE0, 0x00, 0xE1,
0xE0, 0x02, 0xF1, 0xE0, 0x03, 0xE0, 0x00, 0xF2, 0xE0, 0x03,
0x00, 0x01, 0xF0, 0xE0, 0x00, 0xE1, 0xE0, 0x02, 0xF0, 0xE0,
0x01, 0xE1, 0xE0, 0x03, 0xF0, 0xE1, 0xE0, 0x03, 0xE0, 0x00,
0xF0, 0xE1, 0xE0, 0x02, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0xE0,
0x01, 0xF2, 0xE0, 0x00, 0x00, 0x01, 0xF0, 0xE0, 0x00, 0xE1,
0xE0, 0x00, 0xF0, 0xE0, 0x01, 0xE0, 0x02, 0xF4, 0xE0, 0x01,
0xF1, 0xE0, 0x01, 0x00, 0x02, 0xF0, 0xE0, 0x01, 0xE1, 0xE0,
0x01, 0xF5, 0xE0, 0x00, 0xE0, 0x01, 0xF1, 0xE0, 0x00, 0xE0,
0x02, 0xF0, 0xE0, 0x01, 0xE0, 0x02, 0xF4, 0xE0, 0x01, 0xF1,
0xE0, 0x01, 0x00, 0x02, 0xF0, 0xE1, 0xE0, 0x01, 0xE0, 0x00,
0xF0, 0xE0, 0x01, 0xE0, 0x02, 0xF4, 0xE0, 0x01, 0xF6, 0xE0,
0x01, 0x20, 0x00, 0xF7, 0x94, 0xF8
};
int eflag = 0;
unsigned char string[] = "abcd";
unsigned int n[4] = { 0 }; //寄存器
int mov(int x) {
int i = 0;
for (i = 1;; i++) {
if (opcode[x + i] > 0xEF) {
break;
}
}
if (i == 6) {
if (opcode[x + 1] == 0xE0) {
if (opcode[x + 4] == 0xE0) {
printf("e%cx = s[e%cx]\n", string[opcode[x + 2]], string[opcode[x + 5]]);
}
else {
printf("e%cx = s[%d]\n", string[opcode[x + 2]], (opcode[x + 5] << 8) + opcode[x + 4]);
}
}
else if (opcode[x + 1] == 0xE1) {
printf("s[e%cx] = e%cx\n", string[opcode[x + 3]], string[opcode[x + 5]]);
}
return 6;
}
else if(i<=6){
if (i == 4) {
printf("e%cx = %d\n", string[opcode[x + 2]], opcode[x + 3]);
return 4;
}
else if (i == 5) {
printf("e%cx = e%cx\n",string[opcode[x + 2]],string[opcode[x + 4]]);
return 5;
}
}
}
int add(int i) {
if (opcode[i + 3] == 0xE0) {
printf("add e%cx e%cx\n", string[opcode[i + 2]], string[opcode[i + 4]]);
}
else {
printf("add e%cx %d\n", string[opcode[i + 2]], ((opcode[i + 4] << 8) + opcode[i + 3])); //注意运算符优先级
}
return 5;
}
int mod(int i) {
if (opcode[i + 3] == 0xE0) {
printf("e%cx mod e%cx\n", string[opcode[i + 2]],string[opcode[i + 4]]);
}
else {
printf("e%cx mod %d\n", string[opcode[i + 2]], ((opcode[i + 4] << 8) + opcode[i + 3]));
}
return 5;
}
int inc(int i) {
printf("e%cx ++\n", string[opcode[i + 2]]);
return 3;
}
int dec (int i) {
printf("e%cx --\n",string[opcode[i + 2]]);
return 3;
}
int x0r(int i) {
printf(" xor e%cx e%cx\n",string[opcode[i + 2]],string[opcode[i + 4]]);
return 5;
}
int cmp(int i) {
printf("cmp e%cx 0x%x\n", string[opcode[i + 2]], ((opcode[i + 4] << 8) + opcode[i + 3]));
return 5;
}
int jmp(int i) {
printf("jmp %d\n=========\n",opcode[i + 1]);
return 2;
}
int main()
{
int i = 0;
while (1) {
if (opcode[i] == 0xF8) {
break;
}
switch (opcode[i])
{
case 0xf0:
i += mov(i);
break;
case 0xf1:
i += add(i);
break;
case 0xf2:
i += mod(i);
break;
case 0xf3:
i += inc(i);
break;
case 0xf4:
i += dec(i);
break;
case 0xf5:
i += x0r(i);
break;
case 0xf6:
i += cmp(i);
break;
case 0xf7:
i += jmp(i);
break;
default:
break;
}
}
printf("retn");
return 0;
}
打印出来的伪汇编代码大致是这样的。
ecx = 0 初始化s和key
eax = ecx
s[ecx] = ecx
ebx = 16
eax mod ebx
add eax 544
eax = s[eax]
ebx = ecx
add ebx 256
s[ebx] = eax
ecx ++
cmp ecx 0x100
jmp 4
========= 生成密钥流
ecx = 0
edx = 0
eax = s[ecx]
add edx eax
eax = ecx
add eax 256
eax = s[eax]
add edx eax
edx mod 256
eax = s[ecx]
ebx = s[edx]
s[edx] = eax
s[ecx] = ebx
ecx ++
cmp ecx 0x100
jmp 69
=========
ecx = 0 加密部分
edx = 0
ecx ++
ecx mod 256 ecx++
eax = s[ecx]
add edx eax
edx mod 256
eax = s[ecx]
ebx = s[edx]
s[edx] = eax
s[ecx] = ebx
add eax ebx
eax mod 256
eax = s[eax]
ebx = ecx
ebx --
add ebx 512
ebx = s[ebx]
xor eax ebx data[i] ^= s[t]
add eax ecx data[i] += ecx
ebx = ecx
ebx --
add ebx 512
s[ebx] = eax
ebx = ecx
ebx --
cmp ebx 0x20
jmp 148
=========
retn
不难发现这是rc4加密,但是这里有魔改。在进行异或之后还加上了 i.
#include<stdio.h>
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{
int i = 0, j = 0;
char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i < 256; i++) {
s[i] = i;
k[i] = key[i % Len_k];
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
/*
RC4加解密函数
unsigned char* Data 加解密的数据
unsigned long Len_D 加解密数据的长度
unsigned char* key 密钥
unsigned long Len_k 密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
unsigned char s[256];
rc4_init(s, key, Len_k);
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
int result = 0;
for (k = 0; k < Len_D; k++) {
i = (i + 1) % 256;
result = i;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = (s[i] + s[j]) % 256;
Data[k] = (Data[k]-i) ^ s[t];
}
}
void main()
{
//字符串密钥
unsigned char key[] = "This_1s_f1lLllag";
unsigned long key_len = sizeof(key) - 1;
//数组密钥
//unsigned char key[] = {};
//unsigned long key_len = sizeof(key);
//加解密数据
unsigned char data[] = { 0x56, 0x54, 0xD9, 0xB5, 0xF3, 0xB1, 0xFD, 0x67, 0x15, 0xEE,
0xB0, 0x68, 0xB7, 0x2B, 0x4A, 0x64, 0x10, 0x27, 0x52, 0xDE,
0x43, 0x26, 0x0F, 0x2A, 0x41, 0x30, 0x75, 0x30, 0x98, 0x9E,
0x79, 0x5E };
//加解密
rc4_crypt(data, sizeof(data), key, key_len);
for (int i = 0; i < 32; i++)
{
printf("%c", data[i]);
}
printf("\n");
return;
}//711df52879efbcb8964b6056d926ea35