现在是半夜,我不小心打字覆盖了我所有的工作
gcc source.c -o source.c
Run Code Online (Sandbox Code Playgroud)
我仍然拥有原始的二进制文件,我唯一的希望是对其进行反汇编,但我不知道如何或使用什么最好的工具来获得最易读的结果。我知道这可能不是发帖的正确位置,但我很紧张。有人可以帮我吗?
感谢您上传文件。正如我所怀疑的那样,它没有被剥离,所以函数名称仍然存在。除了标准样板代码之外,我还可以识别函数main
, register_broker
, connect_exchange
(未使用和空的)和handle_requests
.
我在 IDA Pro 上花了一些时间,恢复该main()
功能并不太难。首先,这是main()
来自 IDA 的未经修改的原始列表:http : //pastebin.com/sBxhRJMM
要继续,您需要熟悉AMD64 调用约定。总而言之,前四个参数在 RDI(EDI)、RSI(ESI)、RDX(EDX) 和 RCX(ECX) 中传递。其余部分在堆栈上传递,但所有调用main()
最多只使用四个参数,因此我们无需担心。
IDA 有用地标记了标准 C 函数的参数,甚至重命名了一些局部变量。但是,它可以进一步改进和评论。例如,因为我们在 中main()
,我们知道argc
(第一个参数)来自 EDI(因为它是一个int
32 位的含义,它只使用 RDI 的低半部分)并且argv
来自 RSI(它是一个指针,所以它使用完整的8 个字节的寄存器)。因此,我们可以重命名 EDI 和 RSI 复制到的局部变量:
mov [rbp+argc], edi
mov [rbp+argv], rsi
Run Code Online (Sandbox Code Playgroud)
接下来是一个简单的条件块:
mov [rbp+argc], edi
mov [rbp+argv], rsi
Run Code Online (Sandbox Code Playgroud)
这里我们将 argc 与 2 进行比较,如果相等,则在代码中进一步跳转。如果不相等,我们调用fwrite()
。它的第一个参数是 in rdi
,并且rdi
是从 加载的rax
,它保存着一个常量字符串“Usage”的地址。第二个参数是 inesi
并且是 1,第三个 inedx
并且是 5,第四个 in rcx
,从rdx
它加载的值为stderr@@GLIBC_2_2_5
,这基本上是对stderr
来自 libc的变量的奇特引用。把它们串起来,我们得到:
fwrite("Usage", 1, 5, stderr);
Run Code Online (Sandbox Code Playgroud)
根据我的经验,我可以说它很可能是一个 inlined fprintf
,因为 5 正是字符串的长度。即原始代码可能是:
fprintf(stderr, "Usage");
Run Code Online (Sandbox Code Playgroud)
下一个调用是一个简单的exit(1);
. 将两者与比较相结合,我们得到:
if ( argc != 2 )
{
fprintf(stderr, "Usage");
exit(1);
}
Run Code Online (Sandbox Code Playgroud)
继续这样,我们可以识别他们使用的其他调用和变量。描述这一切有点乏味,所以我上传了反汇编的注释版本,我试图在其中显示每个调用的等效 C 代码。你可以在这里看到它:http : //pastebin.com/p5sRSwgQ
从那个评论版本不难想象可能的版本main()
:
int main(int argc, char **argv)
{
if ( argc != 2 )
{
fprintf(stderr, "Usage");
exit(1);
}
char name[256];
gethostname(name, sizeof(name));
struct hostent* _hostent = gethostbyname(name);
struct in_addr *_addr0 = (struct in_addr *)(_hostent->h_addr_list[0]);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(0);
addr.sin_addr.s_addr = _addr0->s_addr;
char *tmp = (char *)malloc(6);
sprintf(tmp, "%d", addr.sin_port);
char *ip_str = inet_ntoa(*_addr0);
char *newbuf = (char *)malloc(strlen(argv[1]) + strlen(ip_str) + strlen(tmp) + 5);
strcpy(newbuf, "r");
strcat(newbuf, " ");
strcat(newbuf, argv[1]);
strcat(newbuf, " ");
strcat(newbuf, ip_str);
strcat(newbuf, " ");
strcat(newbuf, tmp);
register_broker(newbuf);
int fd = socket(PF_INET, SOCK_STREAM, 0);
if ( fd < 0 )
{
perror("Error creating socket");
exit(1);
}
if ( bind(fd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
{
perror("Error binding socket");
exit(1);
}
if ( listen(fd, 0x80) != 0 )
{
perror("Error listening on socket");
exit(1);
}
handle_requests(fd);
}
Run Code Online (Sandbox Code Playgroud)
恢复其他两个函数留给读者练习:)