실습> 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