Reversing.kr Easy Keygen Writeup

Reversing.kr Easy Keygen を Ghidra で解析しようとしたけど，失敗したので，いつかリベンジするために記録に残しておく。

http://reversing.kr/challenge.php

問題としては，exeとtxtが渡される。
textの内容

```
Find the Name when the Serial is 5B134977135E7D13
```
シリアルが5B134977135E7D13になる名前を見つけろってことみたいです。



まずは IDA free で解析
手っ取り早くやるときの常とう手段である　xor を検索する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/198427f3-3706-f1ef-3167-82b05d4dc3a6.png)
変数の初期化以外では，アドレス 00401088 の xor があやしい。

ここです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/59ba9a0c-ae50-6190-2564-788868a70381.png)
ループしてるし，復号ルーチンの可能性アリです。

ecx に代入される値のアドレスの一部である var_130 に着目すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/f9de50cc-bc0b-66f0-9cf7-4b22dfe11165.png)
0x10が最初に代入されています
var_12F や var_12Eも気になります。

宣言はこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/9b30cf73-5e65-1ac0-c7d4-33020d35ab00.png)

xorのループのインクリメントに着目すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/0b936095-dd4e-1705-6c6f-82e4f8844a75.png)
esi が暗号化keyのindexとわかるし，key長さが3byteとわかる。

すなわち先ほど見た
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/fd8614a1-81d8-8e20-7610-2b84dd32ef3d.png)
が　xor の key

ソルバー書いてみる

```python
# Find the Name when the Serial is 5B134977135E7D13
ext = "\x5B\x13\x49\x77\x13\x5E\x7D\x13"
dec = ""
j=0
key = '\x10\x20\x30'
for i in range(len(ext)):
    dec = dec + chr(ord(ext[i]) ^ ord(key[i % len(key) ]))
print(dec)
```
ビンゴ！

-----------
さて，ここからが本題

~~残念ながら，Ghidraでは xor を検索できない。~~
Ghidraでも xor を検索できるときがある。（インポート直後だけ？）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/8e2cddb6-000a-1578-1eb0-c55a0cb26821.png)

（参考）ピンク先生のgithubにnon_zero_xor_search.pyというのがあるが，たくさん発見されすぎて困ってしまう。

https://github.com/AllsafeCyberSecurity/ghidra_scripts


初期のデコンパイル結果

```c
undefined4 FUN_00401000(void)
{
  char cVar1;
  byte bVar2;
  byte *pbVar3;
  int iVar4;
  void *this;
  uint uVar5;
  void *this_00;
  int iVar6;
  byte *pbVar7;
  char *pcVar8;
  undefined4 *puVar9;
  bool bVar10;
  undefined local_12c;
  undefined4 local_12b;
  byte local_c8;
  undefined4 local_c7;
  
  iVar4 = 0x18;
  local_12c = 0;
  local_c8 = 0;
  puVar9 = (undefined4 *)(&local_12c + 1);
  while (iVar4 != 0) {
    iVar4 = iVar4 + -1;
    *puVar9 = 0;
    puVar9 = puVar9 + 1;
  }
  *(undefined2 *)puVar9 = 0;
  *(undefined *)((int)puVar9 + 2) = 0;
  iVar4 = 0x31;
  puVar9 = &local_c7;
  while (iVar4 != 0) {
    iVar4 = iVar4 + -1;
    *puVar9 = 0;
    puVar9 = puVar9 + 1;
  }
  *(undefined2 *)puVar9 = 0;
  *(undefined *)((int)puVar9 + 2) = 0;
  FUN_004011b9((byte *)s_Input_Name:_00408060);
  FUN_004011a2(this,&DAT_0040805c);
  uVar5 = 0xffffffff;
  iVar4 = 0;
  iVar6 = 0;
  pcVar8 = &local_12c;
  do {
    if (uVar5 == 0) break;
    uVar5 = uVar5 - 1;
    cVar1 = *pcVar8;
    pcVar8 = pcVar8 + 1;
  } while (cVar1 != '\0');
  if (~uVar5 != 1 && -1 < (int)(~uVar5 - 1)) {
    do {
      if (2 < iVar6) {
        iVar6 = 0;
      }
      FUN_00401150((char *)&local_c8,(byte *)s_%s%02X_00408054);
      iVar4 = iVar4 + 1;
      uVar5 = 0xffffffff;
      iVar6 = iVar6 + 1;
      pcVar8 = &local_12c;
      do {
        if (uVar5 == 0) break;
        uVar5 = uVar5 - 1;
        cVar1 = *pcVar8;
        pcVar8 = pcVar8 + 1;
      } while (cVar1 != '\0');
    } while (iVar4 < (int)(~uVar5 - 1));
  }
  iVar4 = 0x19;
  puVar9 = (undefined4 *)&local_12c;
  while (iVar4 != 0) {
    iVar4 = iVar4 + -1;
    *puVar9 = 0;
    puVar9 = puVar9 + 1;
  }
  FUN_004011b9((byte *)s_Input_Serial:_00408044);
  FUN_004011a2(this_00,&DAT_0040805c);
  pbVar7 = &local_c8;
  pbVar3 = &local_12c;
  do {
    bVar2 = *pbVar3;
    bVar10 = bVar2 < *pbVar7;
    if (bVar2 != *pbVar7) {
LAB_0040110e:
      iVar4 = (1 - (uint)bVar10) - (uint)(bVar10 != 0);
      goto LAB_00401113;
    }
    if (bVar2 == 0) break;
    bVar2 = pbVar3[1];
    bVar10 = bVar2 < pbVar7[1];
    if (bVar2 != pbVar7[1]) goto LAB_0040110e;
    pbVar3 = pbVar3 + 2;
    pbVar7 = pbVar7 + 2;
  } while (bVar2 != 0);
  iVar4 = 0;
LAB_00401113:
  if (iVar4 == 0) {
    FUN_004011b9((byte *)s_Correct!_00408038);
    return 0;
  }
  FUN_004011b9((byte *)s_Wrong_00408030);
  return 0;
}
```

```
00401038 c6 44 24        MOV        byte ptr [ESP + local_130],0x10
0040103d c6 44 24        MOV        byte ptr [ESP + local_12f],0x20
00401042 c6 44 24        MOV        byte ptr [ESP + local_12e],0x30
```

とか

```
0040107e 0f be 4c        MOVSX      ECX,byte ptr [ESP + ESI*0x1 + 0xc]
00401083 0f be 54        MOVSX      EDX,byte ptr [ESP + EBP*0x1 + 0x10]
00401088 33 ca           XOR        ECX,EDX
```

の部分が全くデコンパイルされていない。

また，

```
             undefined1        Stack[-0x12e   local_12e                               XREF[1]:     00401042(W)  
             undefined1        Stack[-0x12f   local_12f                               XREF[1]:     0040103d(W)  
             undefined1        Stack[-0x130   local_130                               XREF[1]:     00401038(W)  
```

と，xor key の部分が認識できていない。
この原因は，たぶん Function Signature の問題だと思うけど，IDAが解読した 

```c
int __cdecl main(int argc, const char **argv, const char **envp)
```

を元にFunction Signatureを変更するも
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/096bf1e3-0fe0-7998-4a2e-35573371251e.png)
const char ** はダメと怒られる。

どうすればいいのだろうか？