gpt4 book ai didi

c - 我需要从可执行文件中恢复我的源代码

转载 作者:太空狗 更新时间:2023-10-29 15:13:31 24 4
gpt4 key购买 nike

半夜了,不小心打字覆盖了所有的工作

gcc source.c -o source.c

我仍然拥有原始的二进制文件,我唯一的希望就是反汇编它,但我不知道如何或使用什么最好的工具来获得最易读的结果。我知道这可能不适合发帖,但我压力很大。有人可以帮我吗?

最佳答案

感谢您上传文件。正如我所怀疑的那样,它没有被剥离,所以函数名称仍然存在。除了标准样板代码外,我还可以识别函数 mainregister_brokerconnect_exchange(未使用且为空)和 handle_requests

我在 IDA Pro 上花了一些时间,恢复 main() 函数并不难。首先,这是来自 IDA 的原始的、未修改的 main() list :http://pastebin.com/sBxhRJMM

要继续,您需要熟悉 AMD64 calling convention .总而言之,前四个参数在 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

接下来是一个简单的条件 block :

cmp     [rbp+argc], 2
jz short loc_400EB3
mov rax, cs:stderr@@GLIBC_2_2_5
mov rdx, rax
mov eax, offset aUsage ; "Usage"
mov rcx, rdx ; s
mov edx, 5 ; n
mov esi, 1 ; size
mov rdi, rax ; ptr
call _fwrite
mov edi, 1 ; status
call _exit

这里我们比较argc和2,如果相等,则在代码中跳得更远。如果它 相等,我们调用fwrite()。它的第一个参数在rdi中,rdi是从rax中加载的,它保存着一个常量字符串“Usage”的地址。第二个参数在esi中为1,第三个在edx中为5,在rcx中为第四个,从加载>rdx 的值为 stderr@@GLIBC_2_2_5,这基本上是对 libc 中的 stderr 变量的奇特引用。把它们串起来,我们得到:

fwrite("Usage", 1, 5, stderr);

根据我的经验,我可以说它很可能是内联的 fprintf,因为 5 恰好是字符串的长度。 IE。原始代码可能是:

fprintf(stderr, "Usage");

下一个调用是一个简单的 exit(1);。将两者与比较相结合,我们得到:

if ( argc != 2 )
{
fprintf(stderr, "Usage");
exit(1);
}

继续沿用这一思路,我们可以确定它们使用的其他调用和变量。描述这一切有点乏味,所以我上传了反汇编的注释版本,我试图在其中显示每个调用的等效 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);
}

恢复其他两个函数留给读者练习:)

关于c - 我需要从可执行文件中恢复我的源代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7379553/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com