[15] gdb 디스어셈블러 사용법,예제 ( C와 어셈블리 )

2017. 11. 3. 19:56SystemHacking/Assembly

 

 

 

gdb 명령어 관련 http://itsaessak.tistory.com/78
 


#include <stdio.h>


char *passwoprd = "th3p4ssw0rd";


int main(){


        // 1036byte

        char buffer[1024];      // ebp- 1024

        char *p;                // ebp-1028

        char *q;                // ebp-1032

        int length;     // ebp-1036


        printf("Input password: ");

        // char *fgets( char *s, int size, FILE *stream);

        fgets(buffer,1024,stdin);


        if ( length > 0 && buffer[length-1] == '\n' ){

                buffer[length-1] = 0 ;



        }


        while ( *p != 0 && *q != 0 && *p = *q ){

                p++;

                q++;

        }


        if ( *p == 0 && *q == 0 ){

                printf("Congratulations! You got it!\n");

        }else {

                printf("Oops! wrong pasword! :-p\n");

        }


        return 0;

}

 



    



# gdb

(gdb) file password1

(gdb) set disassembly-flavor intel

(gdb) disas main

Dump of assembler code for function main:

0x8048460 <main>:       push   %ebp

0x8048461 <main+1>:     mov    %ebp,%esp

0x8048463 <main+3>:     sub    %esp,0x40c         ; 지역변수 1036byte 할당


0x8048469 <main+9>:     push   0x80485b0

0x804846e <main+14>:    call   0x8048398 <printf>         ; printf( 0x80485b0 )

0x8048473 <main+19>:    add    %esp,4

=>

b *0x8048469

x/s 0x80485b0 "Input Password"


0x8048476 <main+22>:    mov    %eax,%ds:0x80496f0

0x804847b <main+27>:    push   %eax

0x804847c <main+28>:    push   0x400

0x8048481 <main+33>:    lea    %eax,[%ebp-1024]

0x8048487 <main+39>:    push   %eax

0x8048488 <main+40>:    call   0x8048368 <fgets>         ; fgets(buffer,1024,stdin)

0x804848d <main+45>:    add    %esp,12


0x8048490 <main+48>:    lea    %eax,[%ebp-1024]

0x8048496 <main+54>:    push   %eax

0x8048497 <main+55>:    call   0x8048378 <strlen>                         ; length = strlen(buffer)

0x804849c <main+60>:    add    %esp,4

0x804849f <main+63>:    mov    DWORD PTR [%ebp-1036],%eax         ; %eax에 length


0x80484a5 <main+69>:    cmp    DWORD PTR [%ebp-1036],0

0x80484ac <main+76>:    jle    0x80484d2 <main+114>


0x80484ae <main+78>:    mov    %eax,DWORD PTR [%ebp-1036]

0x80484b4 <main+84>:    dec    %eax ; len = len - 1

0x80484b5 <main+85>:    lea    %edx,[%ebp-1024] ; buffer

0x80484bb <main+91>:    cmp    BYTE PTR [%eax+%edx],0xa         ; 뉴라인체크

0x80484bf <main+95>:    jne    0x80484d2 <main+114>


0x80484c1 <main+97>:    mov    %eax,DWORD PTR [%ebp-1036]

0x80484c7 <main+103>:   dec    %eax

0x80484c8 <main+104>:   lea    %edx,[%ebp-1024]

0x80484ce <main+110>:   mov    BYTE PTR [%eax+%edx],0x0             ; 뉴라인 제거


0x80484d2 <main+114>:   lea    %ecx,[%ebp-1024] ; buffer시작주소

0x80484d8 <main+120>:   mov    DWORD PTR [%ebp-1028],%ecx             ; *p = buffer

0x80484de <main+126>:   mov    DWORD PTR [%ebp-1032],0x8049608     ; *q = 주소

=> 무슨 주소인지 확인


(gdb) b *0x80484de

Breakpoint 1 at 0x80484de

(gdb) run

Starting program: /root/password1

'Input password: abcd

Breakpoint 1, 0x80484de in main ()

(gdb) x/s 0x8049608

0x8049608 <password>:    "th3p4ssw0rd"


0x80484e8 <main+136>:   mov    %eax,DWORD PTR [%ebp-1028]         ; $eax = *p

0x80484ee <main+142>:   cmp    BYTE PTR [%eax],0x0                         ; *p 와 0 비교

0x80484f1 <main+145>:   je     0x8048512 <main+178>                     ; *p값이 0이라면 점프


0x80484f3 <main+147>:   mov    %eax,DWORD PTR [%ebp-1032] ; 0이 아니라면 비밀번호의 주소를 $eax register에 저장

0x80484f9 <main+153>:   cmp    BYTE PTR [%eax],0x0             ; 패스워드주소의 마지막+1 부분이라면 

0x80484fc <main+156>:   je     0x8048512 <main+178>         ; 점프


0x80484fe <main+158>:   mov    %eax,DWORD PTR [%ebp-1028]                 ; *p

0x8048504 <main+164>:   mov    %edx,DWORD PTR [%ebp-1032]                 ; *q

0x804850a <main+170>:   mov    %al,BYTE PTR [%eax]                     ; buffer의 한글자를 가져온다

0x804850c <main+172>:   cmp    %al,BYTE PTR [%edx]                     ; 패스워드와 비교

0x804850e <main+174>:   je     0x8048514 <main+180>                     ; 같으면 점프


0x8048510 <main+176>:   jmp    0x8048512 <main+178>

0x8048512 <main+178>:   jmp    0x8048522 <main+194>

    ; 다음 문자를 비교하기 위해 포인터를 이동시킨다

0x8048514 <main+180>:   inc    DWORD PTR [%ebp-1028] ; p++

0x804851a <main+186>:   inc    DWORD PTR [%ebp-1032] ; q++

0x8048520 <main+192>:   jmp    0x80484e8 <main+136>


0x8048522 <main+194>:   mov    %eax,DWORD PTR [%ebp-1028]            ; 포인터 p 가

0x8048528 <main+200>:   cmp    BYTE PTR [%eax],0x0            ; 입력한 문자열의 끝을 가리키고있는지 확인

0x804852b <main+203>:   jne    0x8048547 <main+231>         ; 끝이 아니면, 실패 문장 출력


0x804852d <main+205>:   mov    %eax,DWORD PTR [%ebp-1032]        ; 포인터 q가

0x8048533 <main+211>:   cmp    BYTE PTR [%eax],0x0            ; 파일의 password 끝을 가리키고 있는지 확인

0x8048536 <main+214>:   jne    0x8048547 <main+231>        ; 끝이 아니면, 실패 문장 출력


0x8048538 <main+216>:   push   0x80485c1                    ; 성공 !

0x804853d <main+221>:   call   0x8048398 <printf>

0x8048542 <main+226>:   add    %esp,4

=

(gdb) x/s 0x80485c1

0x80485c1 <_IO_stdin_used+21>:   "Congratulations! You got it!\n"


0x8048545 <main+229>:   jmp    0x8048554 <main+244>            ; 실패 !

0x8048547 <main+231>:   push   0x80485df

0x804854c <main+236>:   call   0x8048398 <printf>

0x8048551 <main+241>:   add    %esp,4

=>

(gdb) x/s 0x80485df

0x80485df <_IO_stdin_used+51>:   "Oops! wrong password! :-P\n"


0x8048554 <main+244>:   xor    %eax,%eax

0x8048556 <main+246>:   jmp    0x8048558 <main+248>

0x8048558 <main+248>:   leave

0x8048559 <main+249>:   ret


 

[ 실행결과 ]