4

私は大学でコース (リバース エンジニアリング) を持っていて、宿題があります。.obj ファイル (Visual Studio 2008 でコンパイル) を取得しました。これを逆アセンブルし、制御構造を把握して、小さな C プログラムで呼び出す必要があります。

IDA逆コンパイラを使用しました.asmコードは次のとおりです。

_FB3:
  00000000: 55                 push        ebp
  00000001: 56                 push        esi
  00000002: 57                 push        edi
  00000003: 8B 7C 24 10        mov         edi,dword ptr [esp+10h]
  00000007: 83 3F 00           cmp         dword ptr [edi],0
  0000000A: 74 79              je          00000085
  0000000C: 8D 64 24 00        lea         esp,[esp]
  00000010: 8B 2F              mov         ebp,dword ptr [edi]
  00000012: 8B 75 00           mov         esi,dword ptr [ebp]
  00000015: 8B 44 24 14        mov         eax,dword ptr [esp+14h]
  00000019: 8B CE              mov         ecx,esi
  0000001B: EB 03              jmp         00000020
  0000001D: 8D 49 00           lea         ecx,[ecx]
  00000020: 8A 10              mov         dl,byte ptr [eax]
  00000022: 3A 11              cmp         dl,byte ptr [ecx]
  00000024: 75 1A              jne         00000040
  00000026: 84 D2              test        dl,dl
  00000028: 74 12              je          0000003C
  0000002A: 8A 50 01           mov         dl,byte ptr [eax+1]
  0000002D: 3A 51 01           cmp         dl,byte ptr [ecx+1]
  00000030: 75 0E              jne         00000040
  00000032: 83 C0 02           add         eax,2
  00000035: 83 C1 02           add         ecx,2
  00000038: 84 D2              test        dl,dl
  0000003A: 75 E4              jne         00000020
  0000003C: 33 C0              xor         eax,eax
  0000003E: EB 05              jmp         00000045
  00000040: 1B C0              sbb         eax,eax
  00000042: 83 D8 FF           sbb         eax,0FFFFFFFFh
  00000045: 85 C0              test        eax,eax
  00000047: 7D 05              jge         0000004E
  00000049: 8D 7D 0C           lea         edi,[ebp+0Ch]
  0000004C: EB 32              jmp         00000080
  0000004E: 8B 44 24 14        mov         eax,dword ptr [esp+14h]
  00000052: 8B CE              mov         ecx,esi
  00000054: 8A 10              mov         dl,byte ptr [eax]
  00000056: 3A 11              cmp         dl,byte ptr [ecx]
  00000058: 75 1A              jne         00000074
  0000005A: 84 D2              test        dl,dl
  0000005C: 74 12              je          00000070
  0000005E: 8A 50 01           mov         dl,byte ptr [eax+1]
  00000061: 3A 51 01           cmp         dl,byte ptr [ecx+1]
  00000064: 75 0E              jne         00000074
  00000066: 83 C0 02           add         eax,2
  00000069: 83 C1 02           add         ecx,2
  0000006C: 84 D2              test        dl,dl
  0000006E: 75 E4              jne         00000054
  00000070: 33 C0              xor         eax,eax
  00000072: EB 05              jmp         00000079
  00000074: 1B C0              sbb         eax,eax
  00000076: 83 D8 FF           sbb         eax,0FFFFFFFFh
  00000079: 85 C0              test        eax,eax
  0000007B: 7E 1E              jle         0000009B
  0000007D: 8D 7D 08           lea         edi,[ebp+8]
  00000080: 83 3F 00           cmp         dword ptr [edi],0
  00000083: 75 8B              jne         00000010
  00000085: 6A 10              push        10h
  00000087: E8 00 00 00 00     call        _malloc
  0000008C: 83 C4 04           add         esp,4
  0000008F: 89 07              mov         dword ptr [edi],eax
  00000091: 85 C0              test        eax,eax
  00000093: 75 14              jne         000000A9
  00000095: 5F                 pop         edi
  00000096: 5E                 pop         esi
  00000097: 33 C0              xor         eax,eax
  00000099: 5D                 pop         ebp
  0000009A: C3                 ret
  0000009B: 8B C5              mov         eax,ebp
  0000009D: FF 40 04           inc         dword ptr [eax+4]
  000000A0: 5F                 pop         edi
  000000A1: 5E                 pop         esi
  000000A2: B8 01 00 00 00     mov         eax,1
  000000A7: 5D                 pop         ebp
  000000A8: C3                 ret
  000000A9: 8B 74 24 14        mov         esi,dword ptr [esp+14h]
  000000AD: 8B C6              mov         eax,esi
  000000AF: 8D 50 01           lea         edx,[eax+1]
  000000B2: 8A 08              mov         cl,byte ptr [eax]
  000000B4: 40                 inc         eax
  000000B5: 84 C9              test        cl,cl
  000000B7: 75 F9              jne         000000B2
  000000B9: 2B C2              sub         eax,edx
  000000BB: 40                 inc         eax
  000000BC: 50                 push        eax
  000000BD: E8 00 00 00 00     call        _malloc
  000000C2: 8B 0F              mov         ecx,dword ptr [edi]
  000000C4: 89 01              mov         dword ptr [ecx],eax
  000000C6: 8B 07              mov         eax,dword ptr [edi]
  000000C8: 83 C4 04           add         esp,4
  000000CB: 83 38 00           cmp         dword ptr [eax],0
  000000CE: 74 C5              je          00000095
  000000D0: 8B 10              mov         edx,dword ptr [eax]
  000000D2: 8B CE              mov         ecx,esi
  000000D4: 8A 01              mov         al,byte ptr [ecx]
  000000D6: 88 02              mov         byte ptr [edx],al
  000000D8: 41                 inc         ecx
  000000D9: 42                 inc         edx
  000000DA: 84 C0              test        al,al
  000000DC: 75 F6              jne         000000D4
  000000DE: 8B 17              mov         edx,dword ptr [edi]
  000000E0: C7 42 04 01 00 00  mov         dword ptr [edx+4],1
            00
  000000E7: 8B 07              mov         eax,dword ptr [edi]
  000000E9: C7 40 08 00 00 00  mov         dword ptr [eax+8],0
            00
  000000F0: 8B 0F              mov         ecx,dword ptr [edi]
  000000F2: 5F                 pop         edi
  000000F3: 5E                 pop         esi
  000000F4: C7 41 0C 00 00 00  mov         dword ptr [ecx+0Ch],0
            00
  000000FB: B8 01 00 00 00     mov         eax,1
  00000100: 5D                 pop         ebp
  00000101: C3                 ret

IDA は、次のような優れた制御構造も作成してくれました。 ここに画像の説明を入力

ご覧のとおり、コードは次のようになります。

for(...)
 {
    for1(...){...}
    ...
    for1(...){...}
 }

 malloc
 ....
 for3() ...
 malloc
 ...
 for2(...)
 {
    ...
 }

for1 と for2 がほぼ同じ構造を持っていることを知っているので、アクティビティのみが異なり、for3 の実装された関数は for1 と for2 として functionfamily にあります。for3 は 2 番目の malloc の結果をパラメーターとして使用するので、for2 は何らかの配列コピー ループである必要があると思います。for1、for2、および for3 は、既知の stdc インライン実装です。

この f3 関数の目的を理解する方法を教えてもらえますか?

2 番目の質問: この .obj ファイルを小さなサンプル C プログラムで使用するにはどうすればよいですか? VSでその機能を呼び出すにはどうすればよいですか?

事前に感謝します。どんな助けでも大歓迎です。

更新: 道化師: 興味深い。ノードの構造についてどのように知りましたか? 私はまだこのすべてを(あなたの助けを借りて)理解しようとしていますが、まだ何もありません.

IDA逆アセンブラーには疑似コード表示機能があることがわかりました。ここに疑似があります:

signed int __cdecl FB3(int a1, const char *a2)
{
  int v2; // edi@1
  const char **v3; // ebp@2
  void *v4; // eax@7
  signed int result; // eax@8
  int v6; // edx@11
  const char *v7; // ecx@11
  const char v8; // al@12

  v2 = a1;
  while ( *(_DWORD *)v2 )
  {
    v3 = *(const char ***)v2;
    if ( strcmp(a2, **(const char ***)v2) >= 0 )
    {
      if ( strcmp(a2, **(const char ***)v2) <= 0 )
      {
        ++v3[1];
        return 1;
      }
      v2 = (int)(v3 + 2);
    }
    else
    {
      v2 = (int)(v3 + 3);
    }
  }
  v4 = malloc(0x10u);
  *(_DWORD *)v2 = v4;
  if ( v4 && (**(_DWORD **)v2 = malloc(strlen(a2) + 1)) != 0 )
  {
    v6 = **(_DWORD **)v2;
    v7 = a2;
    do
    {
      v8 = *v7;
      *(_BYTE *)v6++ = *v7++;
    }
    while ( v8 );
    *(_DWORD *)(*(_DWORD *)v2 + 4) = 1;
    *(_DWORD *)(*(_DWORD *)v2 + 8) = 0;
    *(_DWORD *)(*(_DWORD *)v2 + 12) = 0;
    result = 1;
  }
  else
  {
    result = 0;
  }
  return result;
}

これから、文字列内の数字の出現をカウントするのでしょうか? この疑似コードは、私には少しわかりにくいです。

サンプル プログラムでこの関数を呼び出そうとしましたが、成功しませんでした。私が使用した: extern signed int fb3(int a1, const char *a2); それから私はそれを呼び出そうとしましたが、リンカは私に「関数_mainで参照された未解決の外部シンボル_fb3」エラーを与えます(したがって、私が推測するexternキーワードで宣言した.objファイルには、このシグネチャを持つfb3関数はありません。署名が間違っています)。

これが私が使用しようとしたサンプルプログラム(main.c)です:

#include <stdio.h>
extern signed int fb3(int a1, const char *a2);

int main(void)
{
    char b[3] = {'e','3','y'};

    signed int i = fb3(3,b);
    printf("%d",i);

    return 0;
}

リンカー入力 (vs2010) も f3.obj に設定しました。

UPDATE2: ノード構造体を実装し、大文字と小文字を区別する関数名を使用しました。これで、正常にコンパイルできるようになりました。

サンプル プログラム:

#include <stdio.h>

typedef struct node
{
    int count;
    const char * text;
    struct node* right;
    struct node* left;
} node;

extern int FB3(node* root, const char *text);

int main(void)
{
    node* root;
    signed int i;
    int j;

    root = (node*)malloc(sizeof(node));  

    root->count = 0;
    root->text = "textone";
    root->right = NULL;
    root->left = NULL;

    printf("value = %d\n", FB3(root,"v"));
    printf("value = %d\n", FB3(root,"b"));
    printf("value = %d\n", FB3(root,"c"));
    printf("value = %d\n", FB3(root,"3dasf"));
    printf("value = %d\n", FB3(root,"3ssdfs"));
    printf("value = %d\n", FB3(root,"dsda"));
    printf("value = %d\n", FB3(root,"v"));
    printf("value = %d\n", FB3(root,"gsda"));
    printf("value = %d\n", FB3(root,"gsda"));
    printf("value = %d\n", FB3(root,"a"));
    printf("value = %d\n", FB3(root,"ab"));

    return 0;
}

出力は次のとおりです。

 value=1
 value=1
 value=1
 ... (only value=1)

興味深いのは、7 番目の printf が printf "value=2" であることです。これは、"v" が既にツリーに含まれているためです。

4

1 に答える 1

3

一見すると、これは文字列の出現回数をカウントするために使用されるバイナリ ツリーのように見えます。ツリー ノードは次のようになります。

const char* text;
int count;
node* left;
node* right;

関数自体はint addstring(node** root, const char* text) 、最初にツリーが空かどうかをチェックし、空である場合は検索をスキップします。if (strcmp(current->text, text) > 0) current = current->right;検索は、実行してループバックすることにより、0x10 から開始されます。このコードは最適化されていないように見えます。0x4E で同じ比較を行い、今度はチェックし< 0て左に移動します。0x9B は「見つかった」ブランチで、カウンターをインクリメントして 1 を返します。

テキストが見つからない場合、新しいノードが 0x85 に作成され、ツリーに挿入され、テキストが( +strdupとして実装された) を使用してそこにコピーされます。新しいノードのとの両方が に設定され、が 1 に設定されます。malloc(strlen())strcpyleftrightNULLcount

更新malloc:呼び出しからわかるように、ノードのサイズは 16 バイトです。オフセット 0 はテキストの比較に使用されるため、それがテキストである必要があります。オフセット 4 がインクリメントされるため、それがカウンターである必要があります。オフセット 8 と 12 は、そのように使用されるため、2 つの子ポインターです。

IDA が思いついたプロトタイプはナンセンスです。最初の引数はポインタでなければなりません。さもないと爆発します。また、C は大文字と小文字を区別するのでFB3(大文字で) 試してください。このようなもの:

#include <stdio.h>
extern int FB3(void** root, const char *text);

int main(void)
{
    void* root = NULL;
    int i = FB3(&root, "e3y");
    printf("%p %d", root, i);

    return 0;
}

それが機能する場合は、ノード構造体を追加して、C からツリーをトラバースして出力できます。

于 2012-12-02T19:54:44.417 に答える