手脱壳

image

为什么说是自写壳呢 关键是这一行

(Heur) Packer: Generic [Pushal at EP + Last section EP]

意思是

入口点 EP 附近有 PUSHAD/PUSHAL
入口点可能在最后一个 section

哎呀 其实是你die查壳之后打开IDA发现怎么没法反编译啊 又没有SMC 又没有花指令 但是有函数没法反编译 这时候就想到自写壳了 哈哈哈哈

image

ESP定律 这个里面有介绍 这里只实操

由于是32位程序 我使用的是ollydbg 吾爱破解的

image

能看到开头就是pushad 运行一下让他压栈

然后右击ESP 在数据内存转到

然后

image

然后F9运行

image

然后右击

image

image

直接脱壳保存 有一个方式一方式二 方式一脱完壳不能运行但可以静态分析 方式二都可以 脱完壳的

image

  1. 静态分析

main函数 由于能看到前面输出了一句话 所以前面两个函数是输出字符串 到下面有一个if else

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  size_t v3; // eax
  int v5; // [esp+50h] [ebp-1Ch]
  void *v6; // [esp+54h] [ebp-18h]
  const char *Src; // [esp+58h] [ebp-14h]
  int v8; // [esp+5Ch] [ebp-10h]

  sub_4010B4((int)&unk_4395F0, (char *)&byte_432020);
  sub_40107D(sub_40102D);
  if ( --File._cnt < 0 )
    _filbuf(&File);
  else
    ++File._ptr;
  v8 = sub_40108C(&unk_435DC0, 56);
  Src = (const char *)sub_401041((int)&unk_435DC0, (int)&dword_435DF8, 0x38u);
  v6 = malloc(0x64u);
  v3 = strlen(Src);
  memcpy(v6, Src, v3);
  v5 = sub_4010C3(&unk_435DC0, Src, &dword_435E30, 56);
  sub_40101E(v8, Src, v5);
  return 0;
}

这段代码实现的是 getc() 函数

if ( --File._cnt < 0 )
    _filbuf(&File);
else
    ++File._ptr;

加密代码 三个都是简单异或和位移

char *__cdecl sub_401190(int a1, unsigned int a2)
{
  char *v3; // [esp+4Ch] [ebp-Ch]
  signed int i; // [esp+54h] [ebp-4h]

  v3 = (char *)malloc(a2 >> 2);
  for ( i = 0; i < (int)(a2 >> 2); ++i )
    sprintf(&v3[i], "%c", i ^ *(_DWORD *)(a1 + 4 * i));
  return v3;
}
char *__cdecl sub_401240(int a1, _DWORD *a2, size_t Size)
{
  signed int i; // [esp+4Ch] [ebp-Ch]
  char *Buffer; // [esp+50h] [ebp-8h]

  Buffer = (char *)malloc(Size);
  sprintf(Buffer, "%c", *a2);
  for ( i = 1; i < (int)(Size >> 2); ++i )
    sprintf(&Buffer[i], "%c", *(_DWORD *)(a1 + 4 * i) ^ a2[i] ^ *(_DWORD *)(a1 + 4 * i - 4));
  return Buffer;
}
char *__cdecl sub_401320(int a1, int a2, int a3, unsigned int a4)
{
  signed int i; // [esp+4Ch] [ebp-10h]
  char *v6; // [esp+50h] [ebp-Ch]
  char *Source; // [esp+54h] [ebp-8h]

  Source = (char *)malloc(a4 - 1);
  v6 = (char *)malloc(4 * a4 - 1);
  for ( i = 0; i < (int)((a4 >> 2) - 1); ++i )
  {
    sprintf(&v6[i], "%c", *(_DWORD *)(a3 + 4 * i + 4) ^ *(char *)(i + a2));
    sprintf(&Source[i], "%c", i ^ v6[i]);
  }
  sprintf(&Destination, "%c", dword_435E30 ^ dword_435DF8);
  strcat(&Destination, Source);
  return &Destination;
}

数据

unk_435DC0 = [0x66, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00]
dword_435DF8 = [0x37, 0x00, 0x00, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00]
dword_435E30 = [0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00]

exp 懒得写 从网上p一个 嘿嘿

unk_435DC0 = [0x66, 0x6D, 0x63, 0x64, 0x7F, 0x37, 0x35, 0x30, 0x30, 0x6B, 0x3A, 0x3C, 0x3B, 0x20]  
dword_435DF8 = [0x37, 0x6F, 0x38, 0x62, 0x36, 0x7C, 0x37, 0x33, 0x34, 0x76, 0x33, 0x62, 0x64, 0x7A]  
dword_435E30 = [0x1A, 0x00, 0x00, 0x51, 0x05, 0x11, 0x54, 0x56, 0x55, 0x59, 0x1D, 0x09, 0x5D, 0x12]  
  
v8 = ""  
for i in range(0, 14):  
    v8 += chr(i ^ unk_435DC0[i])  
print(v8)  
  
  
Src = ""  
Src += chr(dword_435DF8[0]) 
for j in range(1, 14):  
    Src += chr(unk_435DC0[j] ^ dword_435DF8[j] ^ unk_435DC0[j - 1])  
print(Src)  
  
  
Source = ""  
for k in range(0, 13):  
    Source += chr(k ^ dword_435E30[k + 1] ^ ord(Src[k]))  
Destination = ""  
Destination = chr(dword_435DF8[0] ^ dword_435E30[0])  
v5 = Destination + Source  
print(v5)  
  
  
flag = v8 + Src + v5  
print(flag)
  1. 动态解密

由于我们能看到都是异或 然后通过查看最后一个main里面的最后一个函数能看到是一个拼接函数 那拼接肯定会有显示呀 所以我们直接在这里下断点

sub_40101E(v8, Src, v5);

image

flag

flag{2378b077-7d6e-4564-bdca-7eec8eede9a2}

一把梭

image