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 使用第二个 malloc 的结果作为参数,所以我认为 for2 应该是某种数组复制循环。for1、for2 和 for3 是已知的 stdc 内联实现。

有人可以帮我弄清楚这个 f3 函数的目的吗?

第二个问题:如何在一个小示例 C 程序中使用这个 .obj 文件?我如何在 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) 首先代码检查树是否为空,如果是则跳过搜索。搜索从 0x10 开始,通过执行if (strcmp(current->text, text) > 0) current = current->right;和循环返回。这段代码看起来并没有优化,在 0x4E 它做了同样的比较,这次检查< 0并离开。在 0x9B 是“找到”分支,它增加计数器并返回 1。

如果未找到文本,则在 0x85 创建一个新节点,将其插入树中,然后使用strdup(实现为malloc(strlen())+ strcpy)将文本复制到其中。新节点的 和 都设置为和为left1 。rightNULLcount

更新malloc:从调用中可以看出,节点大小为 16 个字节。偏移量 0 用于比较文本,因此必须是文本。偏移量 4 递增,因此它必须是计数器。偏移量 8 和 12 是两个子指针,因为它们是这样使用的。

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 回答