Reversing.kr Easy Crack Writeup Using Ghidra

IDA freeで逆アセンブルした結果を見た方が速いが，勉強のため，あえてGhidraで解析してみた。

http://reversing.kr/challenge.php

Defined Strings で突破口 Congratulation を発見。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/7ee31ca5-88cc-5e21-cd12-aebb1f8bf263.png)

XREF から FUN_00401080 が mainの処理 とわかる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/5b84c6b6-e334-5331-042d-ff300874ed46.png)

最初のデコンパイル結果

```c
void __cdecl FUN_00401080(HWND param_1)
{
  byte bVar1;
  byte *pbVar2;
  int iVar3;
  char *pcVar4;
  undefined4 *puVar5;
  bool bVar6;
  char local_64;
  char local_63;
  char local_62;
  byte abStack97 [97];
  
  iVar3 = 0x18;
  local_64 = '\0';
  puVar5 = (undefined4 *)&local_63;
  while (iVar3 != 0) {
    iVar3 = iVar3 + -1;
    *puVar5 = 0;
    puVar5 = puVar5 + 1;
  }
  *(undefined2 *)puVar5 = 0;
  *(undefined *)((int)puVar5 + 2) = 0;
  GetDlgItemTextA(param_1,1000,&local_64,100);
  if (local_63 == 'a') {
    iVar3 = _strncmp(&local_63 + 1,&DAT_00406078,2);
    if (iVar3 == 0) {
      pcVar4 = s_AGR3versing_0040606a;
      pbVar2 = (byte *)(&local_63 + 3);
      do {
        pcVar4 = (char *)((byte *)pcVar4 + 2);
        bVar1 = *pbVar2;
        bVar6 = bVar1 < (byte)*pcVar4;
        if (bVar1 != *pcVar4) {
LAB_00401102:
          iVar3 = (1 - (uint)bVar6) - (uint)(bVar6 != 0);
          goto LAB_00401107;
        }
        if (bVar1 == 0) break;
        bVar1 = pbVar2[1];
        bVar6 = bVar1 < ((byte *)pcVar4)[1];
        if (bVar1 != ((byte *)pcVar4)[1]) goto LAB_00401102;
        pbVar2 = pbVar2 + 2;
      } while (bVar1 != 0);
      iVar3 = 0;
LAB_00401107:
      if ((iVar3 == 0) && (local_64 == 'E')) {
        MessageBoxA(param_1,s_Congratulation_!!_00406044,s_EasyCrackMe_00406058,0x40);
        EndDialog(param_1,0);
        return;
      }
    }
  }
  MessageBoxA(param_1,s_Incorrect_Password_00406030,s_EasyCrackMe_00406058,0x10);
  return;
}
```

GetDlgItemTextAについてネットで調べる

```c
UINT GetDlgItemTextA(
  HWND  hDlg,
  int   nIDDlgItem,
  LPSTR lpString,
  int   cchMax
);
```

buffer である local_64 の定義が char となっているので　local_64　の型を char[100] に変更し，名前を Buffer にする。（100は，第4引数の maximum length = 100 が根拠）

変更前

```c
  char local_64;
  char local_63;
  char local_62;
  byte abStack97 [97];
```

変更後（余計な変数が消える）

```c
char buffer [100];
```


----------

DAT_00406078 を見てみると文字列ぽいので，型を文字列に変更する。

変更前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/564f4425-9b8e-0b2e-7ef1-2c89d163bda3.png)


変更後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/9c902141-050a-d08c-e080-3f3bd638548e.png)

---------

逆アセンブル（左）とデコンパイル（右）で string の扱いに矛盾がある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/71cbae42-ecda-712b-4d46-370e5550fdef.png)

逆アセンブル
s_R3versing_0040606c

デコンパイル
s_AGR3versing_0040606a

いったん byte に戻し， R から string に定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/8a21e982-5642-559d-bbf7-fa8cfdfa3499.png)

-----------------------------

Ghidraのデコンパイル誤りを正した結果

```c
void __cdecl FUN_00401080(HWND param_1)
{
  byte bVar1;
  byte *pbVar2;
  int iVar3;
  char *pcVar4;
  undefined4 *puVar5;
  bool bVar6;
  char buffer [100];
  
  iVar3 = 0x18;
  buffer[0] = '\0';
  puVar5 = (undefined4 *)(buffer + 1);
  while (iVar3 != 0) {
    iVar3 = iVar3 + -1;
    *puVar5 = 0;
    puVar5 = puVar5 + 1;
  }
  *(undefined2 *)puVar5 = 0;
  *(undefined *)((int)puVar5 + 2) = 0;
  GetDlgItemTextA(param_1,1000,buffer,100);
  if (buffer[1] == 'a') {
    iVar3 = _strncmp(buffer + 2,s_5y_00406078,2);
    if (iVar3 == 0) {
      pcVar4 = s_R3versing_0040606c;
      pbVar2 = (byte *)(buffer + 4);
      do {
        bVar1 = *pbVar2;
        bVar6 = bVar1 < (byte)*pcVar4;
        if (bVar1 != *pcVar4) {
LAB_00401102:
          iVar3 = (1 - (uint)bVar6) - (uint)(bVar6 != 0);
          goto LAB_00401107;
        }
        if (bVar1 == 0) break;
        bVar1 = pbVar2[1];
        bVar6 = bVar1 < ((byte *)pcVar4)[1];
        if (bVar1 != ((byte *)pcVar4)[1]) goto LAB_00401102;
        pbVar2 = pbVar2 + 2;
        pcVar4 = (char *)((byte *)pcVar4 + 2);
      } while (bVar1 != 0);
      iVar3 = 0;
LAB_00401107:
      if ((iVar3 == 0) && (buffer[0] == 'E')) {
        MessageBoxA(param_1,s_Congratulation_!!_00406044,s_EasyCrackMe_00406058,0x40);
        EndDialog(param_1,0);
        return;
      }
    }
  }
  MessageBoxA(param_1,s_Incorrect_Password_00406030,s_EasyCrackMe_00406058,0x10);
  return;
}
```
if ((iVar3 == 0) && (buffer[0] == 'E')) {
if (buffer[1] == 'a') {
iVar3 = _strncmp(buffer + 2,s_5y_00406078,2)
から
buffer[0]='E'
buffer[1]='a'
buffer[2]='5'
buffer[3]='y'
とわかる

buffer + 4 以降は s_R3versing_0040606c と比較しているが，ループの加算が

```c
        pbVar2 = pbVar2 + 2;
        pcVar4 = (char *)((byte *)pcVar4 + 2);
```

とループ内で２バイトを比較しているところが若干判りにくい構造となっている。
※比較する文字が必ず偶数というわけではなく，文字列の終端である0x00をチェックして奇数にも対応している。

答えは， Ea5yR3versing