C언어/GDB분석

SW·2023년 4월 6일
0

실습> gdb 사용하기

gdb는 GNU Debugger로 리눅스에서 사용되는 실행파일, 코어파일, 프로세스를 분석하는 디버깅 툴이며 화이트해커에게 절대적으로 필요한 디버깅 툴이다. 
화이트해커가 되기 위해서는 이 툴을 잘 다루어야 하고 이 툴을 이용하면 실행파일의 내부구조를 확인할 수 있고 
실행파일의 소스코드(의사코드라고 함)를 그대로 복원할 수 있다.

참고 : GDB를 이용한 디버깅
http://korea.gnu.org/manual/release/gdb/gdb.html

사용환경: CentOS 7

64bit 리눅스 환경에서는 32bit 환경으로 컴파일이 기본적으로 안되므로 이를 허용하기 위해서는 32bit 환경으로 컴파일할 수 있는 패키지를 설치하면 된다.

CentOS에서 32bit 64bit 바이너리를 얻기 위해서는 아래 패키지들을 설치한다. 
# yum -y install gcc make gdb glibc.i686  glibc-devel.i686  libgcc.i686  libstdc++.i686 glibc  glibc-devel  libgcc  libstdc++ 

64bit 용 컴파일 방법: gcc -g -o 실행파일 소스파일 / gcc -g 소스파일 -o 실행파일
32bit 용 컴파일 방법: gcc -m32 -g -o 실행파일 소스파일 / gcc -m32 -g 소스파일 -o 실행파일 

o gdb 실행
gdb를 이용해서 바이너리(실행파일)을 분석하기 위해서는 컴파일 과정에서 디버깅 정보(-g 옵션)를 삽입해야 한다.

컴파일 시 옵션 -g 사용
- 64bit 용 컴파일
# gcc -g -o 실행파일 소스파일
- 32bit 용 컴파일
# gcc -m32 -g -o 실행파일 소스파일

컴파일이 정상적으로 완료되면 GDB를 실행해서 실행파일을 분석한다.

gdb [프로그램명]
# gdb 실행파일

gdb [프로그램명] [프로세스PID]
# gdb main 1928

gdb가 실행되면 (gdb)프롬프트로가 나타나게 된다.

o gdb 종료
gdb를 종료하는 방법에는 네 가지가 있다.

(gdb) ctrl + d
(gdb) q
(gdb) quit
(gdb) exit

o 도움말 출력
- 명령어에 대한 사용법을 알고 싶을 때 사용한다.
(gdb) help
(gdb) help 명령어
(gdb) help x
(gdb) help run

모든 명령어의 도움말을 확인한다.
(gdb) help all

o 메모리 조사
- x 명령어를 사용해서 메모리의 내용을 출력한다.
형식: x/[반복숫자][출력형태][크기] [메모리주소]
출력형태 : o(octal), x(hex), d(decimal), u(unsigned decimal),
           t(binary), f(float), a(address), i(instruction), c(char) and s(string)
크기     : b(byte), h(halfword, 2 bytes), w(word, 4 bytes), g(giant, 8 bytes).

(gdb) x/16xw $ebp
(gdb) x/16xw $ebp-16
(gdb) x/s $ebp-16
(gdb) x/s 0x80484b0

int total = 10;
char name[100] = ....;

(gdb) x/xw total <-- 에러
(gdb) x/s name   <-- 배열명은 메모리 주소이므로

o 어셈블리어로 변환
disassemble 명령어를 사용해서 실행파일을 디스어셈블할  있다.
실행파일에는 기계어 코드(0,1)가 저장되어 있고  기계어코드를 해석해서 어셈블리 코드로 변환해주는 명령어다.

gdb 명령어들을 축약해서 사용할  있다.
run -> r, break -> b, continue -> c
disassemble 을 disas 로 줄여서 사용할 수 있다.
어셈블리 코드를 보여주는 문법이 2가지가 있다.
첫 번째 at&t 문법(default)이고 두 번째는 intel(windows) 문법이 있다.

리눅스에서 어셈블리 코드를 볼 때는 기본값이 at&t 문법이고 intel 문법으로 보기 위해서는 set 명령어를 이용해서 변경할 수 있다.

(gdb) set disassembly-flavor
Requires an argument. Valid arguments are att, intel.

intel 문법으로 변경
- set disassembly-flavor intel
(gdb) set disassembly-flavor intel

at&t 문법으로 변경 (기본값)
- set disassembly-flavor att
(gdb) set disassembly-flavor att

기본값은 at&t 문법으로 실행파일을 디스어셈블할 수 있다.
- 실행파일을 어셈블리 언어로 바꿔서 보여준다.
(gdb) disas main

intel 문법으로 변환해서 보여주기 위해서는 set disassembly-flavor intel 명령어를 사용한다.
(gdb) set disassembly-flavor intel
(gdb) disas main

- /m 옵션은 해당 소스 코드에 대한 어셈블리 코드가 보여진다.
(gdb) disas /m main

- /r 옵션은 해당 기계어 코드가 같이 보여진다.
(gdb) disas /r main

실습> nano 편집기 사용하기

vi 편집기 사용이 어려운 분들은 nono 편집기를 사용한다.
# yum -y install nano
# nano test.txt

  GNU nano 2.3.1               File: test.txt                            Modified

이 파일은 nano 편집기를 사용해서 저장합니다.


^G Get Help  ^O WriteOut  ^R Read File ^Y Prev Page ^K Cut Text  ^C Cur Pos
^X Exit      ^J Justify   ^W Where Is  ^V Next Page ^U UnCut Text^T To Spell

Ctrl + O를 입력하면 아래쪽에 메뉴가 바뀌고 이 상태에서 엔터를 치면 저장된다.

File Name to Write: test.txt
^G Get Help         M-D DOS Format      M-A Append          M-B Backup File
^C Cancel           M-M Mac Format      M-P Prepend

Ctrl + X를 입력하면 종료한다.

실습> gdb 를 이용한 바이너리 분석 1

>>> 간단히 분석하기 <<<

복사 > vi 파일명 > set noai > set paste > i > 붙여넣기

1. 소스 코드 작성
# vi test1.c
/*
 * 파일명: test1.c
 * 프로그램 설명: 바이너리 패치
 * 작성자: 리눅스마스터넷
 * 작성일: 2023.03.18
 *
 * 컴파일: gcc -m32 -g -o test1 test1.c
 */
#include <stdio.h>

int main()
{
    int i = 7;

    printf("i = %d\n", i);  // i = 7

    return 0;
}

2. 컴파일
32bit 환경으로 컴파일 한다.
# gcc -m32 -g -o test1 test1.c
# ./test1
i = 7

# file test1
test1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=726e3b662223e2f47bc521dc0ef817d6c6931c08, not stripped

3. gdb 분석
# alias gdb='gdb -q'
# vi .bashrc
  :
  :(생략)
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias vi='vim'
alias gdb='gdb -q'  <-- 추가
  :
  :(생략)

# gdb test1
(gdb) disas /m main  <-- C언어에 해당하는 어셈블리 코드를 출력한다.
(gdb) disas /r main  <-- 기계어코드와 해당 어셈블리 코드를 출력한다.
(gdb) b main         <-- main() 함수에 BP(Break Point)를 설정한다.
(gdb) r              <-- 프로그램을 실행한다.
(gdb) list           <-- 소스코드를 출력한다.
(gdb) n              <-- 다음 단계로 진행한다.
(gdb) p &i           <-- 변수 i에 저장된 값을 확인한다.
$2 = (int *) 0xffffd62c
(gdb) x/xw  &i       <-- 변수 i의 주소로 값을 확인한다.
0xffffd62c:     0x00000007
(gdb) x/xw 0xffffd62c  <-- 메모리 주소로 값을 확인한다.
0xffffd62c:     0x00000007
(gdb) n                <-- 다음 단계로 진행한다.
i = 7
(gdb) n                <-- 다음 단계로 진행한다.
(gdb) p $eax           <-- 리턴값이 eax 레지스터에 저장되므로 리턴값을 확인한다.
$3 = 0         
(gdb) c                <-- 프로세스 끝까지 실행한다.
(gdb) q                <-- 프로세스를 종료한다.

실습> gdb를 이용한 바이너리 분석하기 2


>>> 자세히 분석하기 <<<

# gdb -q test1
Reading symbols from /root/test1...done.
(gdb) run
Starting program: /root/test1
i = 7
[Inferior 1 (process 2109) exited normally]
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.i686

-g 옵션을 주고 컴파일을 했기 때문에 소스코드를 볼 수 있다.
(gdb) list 1, 50
1       /*
2        * 파일명: test1.c
3        * 프로그램 설명: 바이너리 패치
4        * 작성자: 리눅스마스터넷
5        * 작성일: 2023.03.12
6        *
7        * 컴파일: gcc -m32 -g -o test1 test1.c
8        */
9       #include <stdio.h>
10
11      int main()
12      {
13          int i = 7;
14
15          printf("i = %d\n", i);  // i = 7
16
17          return 0;
18      }

어셈블리 코드가 at&t 문법 형식으로 출력한다.
(gdb) disas main
Dump of assembler code for function main:
   0x0804840d <+0>:     push   %ebp
   0x0804840e <+1>:     mov    %esp,%ebp
   0x08048410 <+3>:     and    $0xfffffff0,%esp
   0x08048413 <+6>:     sub    $0x20,%esp
   0x08048416 <+9>:     movl   $0x7,0x1c(%esp)
   0x0804841e <+17>:    mov    0x1c(%esp),%eax
   0x08048422 <+21>:    mov    %eax,0x4(%esp)
   0x08048426 <+25>:    movl   $0x80484d4,(%esp)
   0x0804842d <+32>:    call   0x80482e0 <printf@plt>
   0x08048432 <+37>:    mov    $0x0,%eax
   0x08048437 <+42>:    leave
   0x08048438 <+43>:    ret
End of assembler dump.

(gdb) disas /r main
Dump of assembler code for function main:
   0x0804840d <+0>:     55      push   %ebp
   0x0804840e <+1>:     89 e5   mov    %esp,%ebp
   0x08048410 <+3>:     83 e4 f0        and    $0xfffffff0,%esp
   0x08048413 <+6>:     83 ec 20        sub    $0x20,%esp
   0x08048416 <+9>:     c7 44 24 1c 07 00 00 00 movl   $0x7,0x1c(%esp)
   0x0804841e <+17>:    8b 44 24 1c     mov    0x1c(%esp),%eax
   0x08048422 <+21>:    89 44 24 04     mov    %eax,0x4(%esp)
   0x08048426 <+25>:    c7 04 24 d4 84 04 08    movl   $0x80484d4,(%esp)
   0x0804842d <+32>:    e8 ae fe ff ff  call   0x80482e0 <printf@plt>
   0x08048432 <+37>:    b8 00 00 00 00  mov    $0x0,%eax
   0x08048437 <+42>:    c9      leave
   0x08048438 <+43>:    c3      ret
End of assembler dump.

(gdb) disas /m main
Dump of assembler code for function main:
12      {
   0x0804840d <+0>:     push   %ebp
   0x0804840e <+1>:     mov    %esp,%ebp
   0x08048410 <+3>:     and    $0xfffffff0,%esp
   0x08048413 <+6>:     sub    $0x20,%esp

13          int i = 7;
   0x08048416 <+9>:     movl   $0x7,0x1c(%esp)

14
15          printf("i = %d\n", i);  // i = 7
   0x0804841e <+17>:    mov    0x1c(%esp),%eax
   0x08048422 <+21>:    mov    %eax,0x4(%esp)
   0x08048426 <+25>:    movl   $0x80484d4,(%esp)
   0x0804842d <+32>:    call   0x80482e0 <printf@plt>

16
17          return 0;
   0x08048432 <+37>:    mov    $0x0,%eax

18      }
   0x08048437 <+42>:    leave
   0x08048438 <+43>:    ret

---Type <return> to continue, or q <return> to quit---
End of assembler dump.


(gdb) b main
Breakpoint 1 at 0x8048416: file test1.c, line 13.

(gdb) i b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08048416 in main at test1.c:13

(gdb) r
Starting program: /root/test1

Breakpoint 1, main () at test1.c:13
13          int i = 7;

(gdb) disas main
Dump of assembler code for function main:
   0x0804840d <+0>:     push   %ebp
   0x0804840e <+1>:     mov    %esp,%ebp
   0x08048410 <+3>:     and    $0xfffffff0,%esp
   0x08048413 <+6>:     sub    $0x20,%esp
=> 0x08048416 <+9>:     movl   $0x7,0x1c(%esp)
   0x0804841e <+17>:    mov    0x1c(%esp),%eax
   0x08048422 <+21>:    mov    %eax,0x4(%esp)
   0x08048426 <+25>:    movl   $0x80484d4,(%esp)
   0x0804842d <+32>:    call   0x80482e0 <printf@plt>
   0x08048432 <+37>:    mov    $0x0,%eax
   0x08048437 <+42>:    leave
   0x08048438 <+43>:    ret
End of assembler dump.

(gdb) disas /m main
Dump of assembler code for function main:
12      {
   0x0804840d <+0>:     push   %ebp
   0x0804840e <+1>:     mov    %esp,%ebp
   0x08048410 <+3>:     and    $0xfffffff0,%esp
   0x08048413 <+6>:     sub    $0x20,%esp

13          int i = 7;
=> 0x08048416 <+9>:     movl   $0x7,0x1c(%esp)

14
15          printf("i = %d\n", i);  // i = 7
   0x0804841e <+17>:    mov    0x1c(%esp),%eax
   0x08048422 <+21>:    mov    %eax,0x4(%esp)
   0x08048426 <+25>:    movl   $0x80484d4,(%esp)
   0x0804842d <+32>:    call   0x80482e0 <printf@plt>

16
17          return 0;
   0x08048432 <+37>:    mov    $0x0,%eax

18      }
   0x08048437 <+42>:    leave
   0x08048438 <+43>:    ret

---Type <return> to continue, or q <return> to quit---
End of assembler dump.

n: next 는 현재 eip 가 가리키고 있는 코드를 실행하고 다음으로 진행한다.
n을 실행하면 i 변수에 7이 저장이 되었다. 
(gdb) n
15          printf("i = %d\n", i);  // i = 7
(gdb) i r
eax            0x1      1
ecx            0x9395a416       -1818909674
edx            0xffffd674       -10636
ebx            0xf7fcc000       -134430720
esp            0xffffd620       0xffffd620
ebp            0xffffd648       0xffffd648
esi            0x0      0
edi            0x0      0
eip            0x804841e        0x804841e <main+17>
eflags         0x282    [ SF IF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0      0
gs             0x63     99

p: print의 약자로 변수의 값을 확인할 때 사용한다.
(gdb) p i
$1 = 7


o 메모리 조사
- x 명령어를 사용해서 메모리의 내용을 출력한다.
형식 : x/[반복숫자][출력형태][크기] [메모리주소]
출력형태 : o(octal), x(hex), d(decimal), u(unsigned decimal),
           t(binary), f(float), a(address), i(instruction), c(char) and s(string)
크기     : b(byte), h(halfword, 2 bytes), w(word, 4 bytes), g(giant, 8 bytes).

(gdb) x/16xw $ebp
(gdb) x/16xw $ebp-16
(gdb) x/s $ebp-16
(gdb) x/s 0x80484b0

i 변수의 주소를 확인한다.
ASLR(Address Space Layout Randomization)의 기법에 의해서 실행할 때마다 메모리에 다르게 올라간다.
공격을 회피하기 위해서 코드를 메모리에 다르게 올린다.
(gdb) p &i
$2 = (int *) 0xffffd63c

(gdb) x/x &i
0xffffd63c:     0x00000007
(gdb) x/x 0xffffd63c
0xffffd63c:     0x00000007

x/16xw &i
x: 메모리 조사 명령어
16: [반복숫자]  
x : [출력형태]  
w : [크기]  
&i: [메모리주소]  
(gdb) x/16xw &i
0xffffd63c:     0x00000007      0x08048440      0x00000000      0x00000000
0xffffd64c:     0xf7e1f2d3      0x00000001      0xffffd6e4      0xffffd6ec
0xffffd65c:     0xf7fd86b0      0x00000001      0x00000001      0x00000000
0xffffd66c:     0x0804a010      0x0804821c      0xf7fcc000      0x00000000

(gdb) n
i = 7
17          return 0;
(gdb) n
18      }
(gdb) c
Continuing.
[Inferior 1 (process 2118) exited normally]
(gdb) q

명령어
# gdb -q test1
l 1, 50
disas main
disas /m main
disas /r main
b main
i b
r
n
p &i
x/x &i
x/16xw &i
n
p $eax
n  c
n
n

# gdb -q test2

(gdb) l 1, 50  <-- 소스코드 1 ~ 50번 라인까지 출력한다.
(gdb) b main <-- main 함수 BP(Break Point)를 설정한다.
(gdb) i b    <-- BP를 확인한다.
(gdb) r      <-- 프로세스를 실행한다.
(gdb) n      <-- int i = 7;에 의해서 i변수에 7이 저장된다.
(gdb) p i    <-- i 변수의 값을 확인한다.
(gdb) p &i   <-- i 변수의 주소를 확인한다.
(gdb) x/16xw &i  <-- i 변수부터 워드(4byte) 단위로 16개의 메모리를 출력한다.
(gdb) n      <-- int j = 3;에 의해서 j변수에 3이 저장된다.
(gdb) p j    <-- j 변수의 값을 확인한다. 
(gdb) p &j   <-- j 변수의 주소를 확인한다.
(gdb) x/16xw &j  <-- j변수를 기점으로 메모리를 워드(4byte) 16개를 출력한다.
0xffffd638:     0x00000003      0x00000007      0x08048450      0x00000000
                ~~~~~~~~~~      ~~~~~~~~~~
                  j 변수            i 변수
0xffffd648:     0x00000000      0xf7e1f2d3      0x00000001      0xffffd6e4
0xffffd658:     0xffffd6ec      0xf7fd86b0      0x00000001      0x00000001
0xffffd668:     0x00000000      0x0804a010      0x0804821c      0xf7fcc000
(gdb) n  <-- 다음 진행
(gdb) n  <-- 다음 진행
(gdb) c  <-- 끝까지 진행
(gdb) q  <-- gdb 종료

실습> 바이너리 분석을 통한 실행파일 패치하기


실행파일: 바이너리(0,1) 파일이라고도 한다.


1. 소스 코드 작성
# vi test1.c
/*
 * 파일명: test1.c
 * 프로그램 설명: 바이너리 패치
 * 작성자: 리눅스마스터넷
 * 작성일: 2023.03.18
 *
 * 컴파일: gcc -m32 -g -o test1 test1.c
 */
#include <stdio.h>

int main()
{
    int i = 7;

    printf("i = %d\n", i);  // i = 7

    return 0;
}

2. 컴파일
# gcc -m32 -g -o test1 test1.c
# ./test1
i = 7

# file test1
test1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=726e3b662223e2f47bc521dc0ef817d6c6931c08, not stripped


3. gdb 분석
# gdb test1
Reading symbols from /root/test1...done.
(gdb) b main
Breakpoint 1 at 0x8048416: file test1.c, line 13.
(gdb) disas /m main
Dump of assembler code for function main:
12      {
   0x0804840d <+0>:     push   %ebp
   0x0804840e <+1>:     mov    %esp,%ebp
   0x08048410 <+3>:     and    $0xfffffff0,%esp
   0x08048413 <+6>:     sub    $0x20,%esp

13          int i = 7;
   0x08048416 <+9>:     movl   $0x7,0x1c(%esp)

14
15          printf("i = %d\n", i);  // i = 7
   0x0804841e <+17>:    mov    0x1c(%esp),%eax
   0x08048422 <+21>:    mov    %eax,0x4(%esp)
   0x08048426 <+25>:    movl   $0x80484d4,(%esp)
   0x0804842d <+32>:    call   0x80482e0 <printf@plt>

16
17          return 0;
   0x08048432 <+37>:    mov    $0x0,%eax

18      }
   0x08048437 <+42>:    leave
   0x08048438 <+43>:    ret

---Type <return> to continue, or q <return> to quit---
End of assembler dump.
(gdb) disas /r main
Dump of assembler code for function main:
   0x0804840d <+0>:     55      push   %ebp
   0x0804840e <+1>:     89 e5   mov    %esp,%ebp
   0x08048410 <+3>:     83 e4 f0        and    $0xfffffff0,%esp
   0x08048413 <+6>:     83 ec 20        sub    $0x20,%esp
   0x08048416 <+9>:     c7 44 24 1c 07 00 00 00 movl   $0x7,0x1c(%esp)
   0x0804841e <+17>:    8b 44 24 1c     mov    0x1c(%esp),%eax
   0x08048422 <+21>:    89 44 24 04     mov    %eax,0x4(%esp)
   0x08048426 <+25>:    c7 04 24 d4 84 04 08    movl   $0x80484d4,(%esp)
   0x0804842d <+32>:    e8 ae fe ff ff  call   0x80482e0 <printf@plt>
   0x08048432 <+37>:    b8 00 00 00 00  mov    $0x0,%eax
   0x08048437 <+42>:    c9      leave
   0x08048438 <+43>:    c3      ret
End of assembler dump.
(gdb) quit

4. 파일 패치
# xxd test1 > test1.xxd
# vi test1.xxd
  :
  :(생략)
64 00003f0: 7416 5589 e583 ec18 c704 2410 9f04 08ff  t.U.......$.....
65 0000400: d0c9 e979 ffff ff90 e973 ffff ff55 89e5  ...y.....s...U..
66 0000410: 83e4 f083 ec20 c744 241c 0800 0000 8b44  ..... .D$......D
                                     ~~ 07 -> 08로 변경
  :
  :(생략)

# xxd -r test1.xxd > test1-2
# chmod 755 test1-2
# file test1-2
test1-2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=726e3b662223e2f47bc521dc0ef817d6c6931c08, not stripped
# ./test1-2
i = 8

실습> 바이너리 분석을 통한 실행파일 패치하기 2

hap 의 값을 13으로 출력한다.

1. 소스 코드 작성
# vi test2.c
/*
 * 파일명: test2.c
 * 프로그램 설명: 바이너리 패치
 * 작성자: 리눅스마스터넷
 * 작성일: 2023.03.18
 *
 * 컴파일: gcc -m32 -g -o test2 test2.c
 */
#include <stdio.h>

int main()
{
    int i = 7;
    int j = 3;
    int hap;

    hap = i + j;

    printf("hap = %d\n", hap);  // hap = 10

    return 0;
}


2. 컴파일
# gcc -m32 -g -o test2 test2.c
# ./test2
hap = 10  <-- 13으로 변경

3. gdb 분석
# gdb test2
(gdb) disas /m main
Dump of assembler code for function main:
12      {
   0x0804840d <+0>:     push   %ebp
   0x0804840e <+1>:     mov    %esp,%ebp
   0x08048410 <+3>:     and    $0xfffffff0,%esp
   0x08048413 <+6>:     sub    $0x20,%esp

13          int i = 7;
   0x08048416 <+9>:     movl   $0x7,0x1c(%esp)

14          int j = 3;
   0x0804841e <+17>:    movl   $0x3,0x18(%esp)

15          int hap;
16
17          hap = i + j;
   0x08048426 <+25>:    mov    0x18(%esp),%eax
   0x0804842a <+29>:    mov    0x1c(%esp),%edx
   0x0804842e <+33>:    add    %edx,%eax
   0x08048430 <+35>:    mov    %eax,0x14(%esp)

18
19          printf("hap = %d\n", hap);  // hap = 10
   0x08048434 <+39>:    mov    0x14(%esp),%eax
   0x08048438 <+43>:    mov    %eax,0x4(%esp)
---Type <return> to continue, or q <return> to quit---disas /m main
   0x0804843c <+47>:    movl   $0x80484e4,(%esp)
   0x08048443 <+54>:    call   0x80482e0 <printf@plt>

20
21          return 0;
   0x08048448 <+59>:    mov    $0x0,%eax

22      }
   0x0804844d <+64>:    leave
   0x0804844e <+65>:    ret

End of assembler dump.
(gdb)
(gdb) disas /r main
Dump of assembler code for function main:
   0x0804840d <+0>:     55      push   %ebp
   0x0804840e <+1>:     89 e5   mov    %esp,%ebp
   0x08048410 <+3>:     83 e4 f0        and    $0xfffffff0,%esp
   0x08048413 <+6>:     83 ec 20        sub    $0x20,%esp
   0x08048416 <+9>:     c7 44 24 1c 07 00 00 00 movl   $0x7,0x1c(%esp)
   0x0804841e <+17>:    c7 44 24 18 03 00 00 00 movl   $0x3,0x18(%esp)
   0x08048426 <+25>:    8b 44 24 18     mov    0x18(%esp),%eax
   0x0804842a <+29>:    8b 54 24 1c     mov    0x1c(%esp),%edx
   0x0804842e <+33>:    01 d0   add    %edx,%eax
   0x08048430 <+35>:    89 44 24 14     mov    %eax,0x14(%esp)
   0x08048434 <+39>:    8b 44 24 14     mov    0x14(%esp),%eax
   0x08048438 <+43>:    89 44 24 04     mov    %eax,0x4(%esp)
   0x0804843c <+47>:    c7 04 24 e4 84 04 08    movl   $0x80484e4,(%esp)
   0x08048443 <+54>:    e8 98 fe ff ff  call   0x80482e0 <printf@plt>
   0x08048448 <+59>:    b8 00 00 00 00  mov    $0x0,%eax
   0x0804844d <+64>:    c9      leave
   0x0804844e <+65>:    c3      ret
End of assembler dump.

어셈블리언어 문법을 intel 문법으로 변경한다.
(gdb) set disassembly-flavor intel
(gdb) disas /r main
Dump of assembler code for function main:
   0x0804840d <+0>:     55      push   ebp
   0x0804840e <+1>:     89 e5   mov    ebp,esp
   0x08048410 <+3>:     83 e4 f0        and    esp,0xfffffff0
   0x08048413 <+6>:     83 ec 20        sub    esp,0x20
   0x08048416 <+9>:     c7 44 24 1c 07 00 00 00 mov    DWORD PTR [esp+0x1c],0x7
   0x0804841e <+17>:    c7 44 24 18 03 00 00 00 mov    DWORD PTR [esp+0x18],0x3
   0x08048426 <+25>:    8b 44 24 18     mov    eax,DWORD PTR [esp+0x18]
   0x0804842a <+29>:    8b 54 24 1c     mov    edx,DWORD PTR [esp+0x1c]
   0x0804842e <+33>:    01 d0   add    eax,edx
   0x08048430 <+35>:    89 44 24 14     mov    DWORD PTR [esp+0x14],eax
   0x08048434 <+39>:    8b 44 24 14     mov    eax,DWORD PTR [esp+0x14]
   0x08048438 <+43>:    89 44 24 04     mov    DWORD PTR [esp+0x4],eax
   0x0804843c <+47>:    c7 04 24 e4 84 04 08    mov    DWORD PTR [esp],0x80484e4
   0x08048443 <+54>:    e8 98 fe ff ff  call   0x80482e0 <printf@plt>
   0x08048448 <+59>:    b8 00 00 00 00  mov    eax,0x0
   0x0804844d <+64>:    c9      leave
   0x0804844e <+65>:    c3      ret
End of assembler dump.

(gdb) quit

4. 파일 패치
# xxd test2 > test2.xxd
# vi test2.xxd
  :
  :(생략)
66 0000410: 83e4 f083 ec20 c744 241c 0700 0000 c744  ..... .D$......D
67 0000420: 2418 0600 0000 8b44 2418 8b54 241c 01d0  $......D$..T$...
  :              ~~ <--  3을 6으로 교체
  :(생략)

# xxd  -r test2.xxd > test2-2
# chmod 755 test2-2
# ./test2-2
hap = 13
profile
정보보안 전문가

0개의 댓글