逆向工程之还原源代码演示

Basic binary reconstruction from assembler
          by c0ntex | c0ntexb@gmail.com      
------------------------------------------

This paper will provide a quick overview of how to perform reverse engineering against a simple .exe binary.
By using the assembly of a binary, it can be trivial to gain a basic understanding of the executable, which
will allow for the source code to be retrieved almost exactly as the developer designed it.

In this example we are only using a small program and as such it is easy to do, on a larger exe it would take
much longer and a more rigerous review of the assembler would be required.


// IDA assembler dump
; seh.exe
.text:0040102B                 push    ebp
.text:0040102C                 mov     ebp, esp  
.text:0040102E                 sub     esp, 0Ch
.text:00401031                 cmp     [ebp+argc], 2
.text:00401035                 jz      short loc_40104B
.text:00401037                 push    offset aUsageSeh_exeBu ; "Usage: seh.exe <buffer>/n"
.text:0040103C                 call    _printf
.text:00401041                 add     esp, 4
.text:00401044                 push    1               ; int
.text:00401046                 call    _exit

.text:0040104B loc_40104B:                             ; CODE XREF: _main+Aj
.text:0040104B                 lea     eax, [ebp+var_C] 
.text:0040104E                 push    eax             ; char * 
.text:0040104F                 mov     ecx, [ebp+argv] 
.text:00401052                 push    ecx             ; int 
.text:00401053                 call    sub_401000 
.text:00401058                 add     esp, 8 
.text:0040105B                 xor     eax, eax 
.text:0040105D                 mov     esp, ebp
.text:0040105F                 pop     ebp 
.text:00401060                 retn 
.text:00401060 _main           endp

.text:00401000 sub_401000      proc near               ; CODE XREF: _main+284p
.text:00401000
.text:00401000 arg_0           = dword ptr  8
.text:00401000 arg_4           = dword ptr  0Ch
.text:00401000
.text:00401000                 push    ebp
.text:00401001                 mov     ebp, esp
.text:00401003                 mov     eax, [ebp+arg_0]
.text:00401006                 mov     ecx, [eax+4]
.text:00401009                 push    ecx             ; char *
.text:0040100A                 mov     edx, [ebp+arg_4]
.text:0040100D                 push    edx             ; char *
.text:0040100E                 call    _strcpy
.text:00401013                 add     esp, 8
.text:00401016                 mov     eax, [ebp+arg_4]
.text:00401019                 push    eax
.text:0040101A                 push    offset aMySehf00IsBett ; "/nMy sehf00 is better than your sehf00 -"...
.text:0040101F                 call    _printf
.text:00401024                 add     esp, 8
.text:00401027                 xor     eax, eax
.text:00401029                 pop     ebp
.text:0040102A                 retn
.text:0040102A sub_401000      endp


So from the above assembler, we can start to replay the instructions into the equivilent c language and have
a fairly good, though not exact, representation of the c *in this case* code used to build the executable.

If there is a piece of code that you are unsure what it's function is, you can write a test c file and run
it through IDA to verify the instructions against what you thought / expected to see.

Dumping the first function only to show how it is done:


push    ebp       ;Back up original stack pointer
mov     ebp, esp      ;            procedure prologue
sub     esp, 0Ch      ;Allocate 12 bytes of space
cmp     [ebp+argc], 2      ;Verify there are 2 arguments passed
jz      short loc_40104B     ;if there are, jump to loc_40104B
push    offset aUsageSeh_exeBu ; "Usage: seh.exe <buffer>/n" ;if not, push error message on stack
call    _printf       ;print the error message
add     esp, 4       ;add 4 to esp
push    1               ; int     ;push exit value
call    _exit       ;exit


probably giving us:


int main(int argc, char **argv)
{
 if(argc != 2) {
   printf("Usage: seh.exe <buffer>/n");
   _exit(1);
  }
something()
}


Do this with each function until we have sourced the entire image. Performing this type of resolution on all
the assembler will provide something like the following:


int main(int argc, char **argv)
{
        char varc[12];
        if(argc != 2) {
                printf("Usage: seh.exe <buffer>/n");
                _exit(1);
        }
        locfunc(argv, varc);
        return(0);
}

locfunc(char **argv, char *varc);
        strcpy(varc, argv[1]);
        printf("My sehf00 is better than your sehf00/n");
        return(0);
}

As you can see we have a fairly complete piece of code, the actual program below is the initial code used to
compile seh.exe and it is obvious that we were real close to the correct syntax. This just shows that even in
a situation when you do not have the applications source to hand, it is still fairly trivial to make by using
a dissassembler to see exactly how the program fits together.

This can be an important skill to have if you want to examine or modify an executable in some manner when you
do not have source code. Say that this application was a piece of malware or a worm that you found on your
system. It would be useful to understand how it worked and perhaps how it got there. By reverse engineering
it, functionality can become apparent straight away and allow you do determine how the program works and what
it does.

// Original seh.exe source
#include<stdio.h>
#include<string.h>
#include<windows.h>

int blah(char *argv[], char *sehheh)
{
        strcpy(sehheh, argv[1]);
 
        printf("/nMy sehf00 is better than your sehf00 -> [%s]/n", sehheh);

        return(0);
}

int main(int argc, char *argv[]){

        char sehheh[12];

        if (argc != 2){
                printf("Usage: myseh.exe <buffer>/n");
                exit(1);
        }

        blah(argv, sehheh);

        return(0);
}

I hope this short paper has been useful in showing how easy it is to perform some basic reverse engineering
of a compiled executable.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值