初音ミクの消失

simple_machine

字数统计: 839阅读时长: 4 min
2019/05/11 Share

simple-machine

simple-machine

思路整理

general

这道题说起来是vm,实际上和vm的挂钩并不大,就是用高级语言去实现了汇编,把变量都当做了寄存器来使用,其中还有各种压栈出栈过程,不过跟本题关系不大,也就不用过于细究了

fun1

fun1主要是通过输入的字符串,与预置的feed进行异或,得到一串加密的字符串,存在内存中

int __cdecl fun1(int str, unsigned int a2)
{
unsigned int v2; // eax
int v3; // eax

push(base_addr_804B15C);
base_addr_804B15C = esp1;
push(temp);
push(temp2);
esp1 -= 48;
*(_DWORD *)(base_addr_804B15C - 29) = 'deef'; // 0x804B13F
*(_DWORD *)(base_addr_804B15C - 25) = 'daed';
*(_DWORD *)(base_addr_804B15C - 21) = 'feeb';
*(_DWORD *)(base_addr_804B15C - 17) = 'efac';
*(_BYTE *)(base_addr_804B15C - 13) = 0;
for ( *(_DWORD *)(base_addr_804B15C - 12) = 0; ; ++*(_DWORD *)(base_addr_804B15C - 12) )// i = base_addr_804B15C - 12
{
eaxx = *(_DWORD *)(base_addr_804B15C - 12); // i
if ( eaxx >= a2 )
break; // 判断是否退出循环
//
//
//
ebxx = *(_DWORD *)(base_addr_804B15C - 12); // i
eaxx = str; // str
temp = ebxx + str; // str + i
ebxx = *(_DWORD *)(base_addr_804B15C - 12); // i
eaxx = ebxx + str; // str + i
eaxx = *(unsigned __int8 *)(ebxx + str); // 取当前字符串
temp1 = eaxx;
*(_BYTE *)(base_addr_804B15C - 41) = eaxx; // 把当前字符串保存到一个地址里面
//
//
//
temp2 = *(_DWORD *)(base_addr_804B15C - 12);
esp1 -= 12;
eaxx = base_addr_804B15C - 29; // 取feed
push(base_addr_804B15C - 29); // push(feed)
v2 = strlen(*(const char **)esp1); // v2 是 feed的长度
esp1 += 16;
len = v2;
eaxx = temp2;
ebxx = 0;
sub_80485AB(v2); // j = i % v2
// i = i / v2
eaxx = ebxx;
eaxx = *(unsigned __int8 *)(ebxx - 29 + base_addr_804B15C);// 算feed中的偏移
temp1 = eaxx;
temp1 = *(_BYTE *)(base_addr_804B15C - 41) ^ eaxx;// c ^ feed[]
*(_BYTE *)temp = temp1;
v3 = eaxx;
LOBYTE(v3) = 0;
eaxx = v3 + (unsigned __int8)temp1;
}
sub_80485A5();
esp1 = base_addr_804B15C - 8;
pop(&temp2);
pop(&temp);
return pop(&base_addr_804B15C);
}

fun2

fun2中有两个循环,看似很复杂实则简单

看到两个寄存器在之间移来移去,发现很多操作都是无效的

void __cdecl fun2(int a1, int a2, int a3)
{
push(base_addr_804B15C);
base_addr_804B15C = esp1;
esp1 -= 16;
for ( *(_DWORD *)(base_addr_804B15C - 4) = 0; // 循环三次
*(_DWORD *)(base_addr_804B15C - 4) <= 2u;
++*(_DWORD *)(base_addr_804B15C - 4) )
{
for ( *(_DWORD *)(base_addr_804B15C - 8) = 0; ; ++*(_DWORD *)(base_addr_804B15C - 8) )
{
len = a3;
ebxx = 1431655766;
eaxx = a3;
sub_80485DB(1431655766); // ebxx = (eaxx * 1431655766) >> 32
ebxx -= (unsigned int)len >> 31;
eaxx = ebxx;
if ( *(_DWORD *)(base_addr_804B15C - 8) >= (unsigned int)ebxx )
break; // 前面一段是关于判断跳出条件的
len = a3;
ebxx = 0x55555556;
eaxx = a3;
sub_80485DB(0x55555556); // ebxx = (unsigned __int64)(a1 * (signed __int64)eaxx) >> 32;
//
ebxx -= (unsigned int)len >> 31;
eaxx = ebxx; // repeated
eaxx = ebxx * *(_DWORD *)(base_addr_804B15C - 4);
ebxx = eaxx;
eaxx = *(_DWORD *)(base_addr_804B15C - 8);
eaxx += ebxx;
ebxx = eaxx;
eaxx = a2;
len = ebxx + a2; // 算偏移地址 addr = 0x804B100 + (i * 18) + j
ebxx = *(_DWORD *)(base_addr_804B15C - 8);
eaxx = 2 * ebxx; // j * 2
ebxx *= 3; // j * 3
eaxx = *(_DWORD *)(base_addr_804B15C - 4);// i
eaxx += ebxx; // i + j * 3
ebxx = eaxx; // i + j * 3
eaxx += a1;
eaxx = *(unsigned __int8 *)(a1 + ebxx); // *(input + i + j * 3)
temp1 = eaxx;
*(_BYTE *)len = eaxx; // 修改上方的那个偏移地址
}
}
sub_80485A5();
}

翻译过来是这样:

for(int i = 0; i <= 2; i++)
for(int j = 0;;j++){
addr[(i * 18) + j] = input + i + j * 3
}

验证

比较fun1和fun2中生成的字符串是否相等

经高人指点,不是比较fun1和fun2的字符串,而是先经过fun1进行处理,然后再经过fun2处理,然后直接和内存中的一串字符串进行比较

solve

feed = "feeddeadbeefcafe"
enc = [0x00,0x03,0x09,0x3A,0x05,0x0E,0x02,0x16,0x0F,0x1F,0x12,0x56,0x3B,0x0B,0x51,0x50,0x39,0x00,0x09,0x1F,0x50,0x04,0x14,0x57,0x3B,0x12,0x07,0x3C,0x1C,0x3A,0x15,0x05,0x0B,0x08,0x06,0x01,0x04,0x12,0x16,0x39,0x05,0x0B,0x50,0x57,0x09,0x12,0x0A,0x27,0x13,0x17,0x0E,0x02,0x55,0x18]
dec = [0x00,0x03,0x09,0x3A,0x05,0x0E,0x02,0x16,0x0F,0x1F,0x12,0x56,0x3B,0x0B,0x51,0x50,0x39,0x00,0x09,0x1F,0x50,0x04,0x14,0x57,0x3B,0x12,0x07,0x3C,0x1C,0x3A,0x15,0x05,0x0B,0x08,0x06,0x01,0x04,0x12,0x16,0x39,0x05,0x0B,0x50,0x57,0x09,0x12,0x0A,0x27,0x13,0x17,0x0E,0x02,0x55,0x18]

for i in range(3):
for j in range(18):
dec[i + j * 3] = enc[i * 18 + j]

ans = ""
for i in range(54):
dec[i] ^= ord(feed[i % 16])
ans = ans + chr(dec[i])

print(ans)

原文作者:mrh929

原文链接:https://mrh1s.top/posts/5f4cc17f/

发表日期:May 11th 2019, 8:45:32 pm

更新日期:May 21st 2019, 3:53:38 pm

版权声明:本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可

CATALOG
  1. 1. simple-machine
    1. 1.1. 思路整理
      1. 1.1.1. general
      2. 1.1.2. fun1
      3. 1.1.3. fun2
      4. 1.1.4. 验证
    2. 1.2. solve