티스토리 뷰
< IN_OUT.exe & IN_OUT2.exe 분석 >
0. Hello.exe 분석
1. 각 프로그램을 한 줄씩 어셈블리어 명령어 행위 작성
2. 어셈블리어 명령어의 의미 작성
3. IN_OUT2.exe 오류 패치
0. Hello.exe 분석
과제 진행에 앞서 수업 시간에 했던 Hello.exe 파일 분석을 정리하려고 한다. 처음 OllyDbg에 들어가서 Hello.exe를 불러오면 [그림 1]과 같은 창이 나타난다. [그림 1]의 OllyDbg는 4구역으로 분리되어 있다. 좌측상단은 메모리 주소, 기계어, 어셈블리어, 주석이 있고, 우측상단은 각종 레지스터들로 구성된다. 좌측하단은 메모리 확인할 수 있고, 우측하단은 스택 영역을 볼 수 있다.
[ OllyDbg 사용법 ]
- F2 : Break Point (설정 시 해당 지점에서 프로그램 실행이 중지됨)
- F7 : Step Into (함수 내부까지 디버깅할 때 사용)
- F8 : Step Over (함수 내부까지 디버깅하고 싶지 않을 때 사용)
- F9 : Run (프로그램 실행)
- CTRL + F2 : Restart (프로그램 재실행)
- CTRL + F7 : Animate Into (F7과 같으나 자동으로 실행)
- CTRL + F8 : Animate Over (F8과 같으나 자동으로 실행)
- CTRL + F9 : Execute till return (F9과 같으나 return까지 실행)
- CTRL + G : Expression (주소로 위치 찾기)
- Enter / - : 분기문이나 함수 호출에서 서브 루틴으로 들어가고 나옴
- * : 현재 실행 중인 위치로 돌아옴
먼저 F9를 눌러서 프로그램을 실행하면 [그림 2]의 좌측상단과 같이 module ntdll이 module Hello로 바뀐다. 이제 main 함수를 찾기 위해 F8을 연속으로 누르면서 한 줄씩 Step Over 해준다. "CALL Hello.00F71040"을 지나는 순간 cmd창에 hello world가 입력된다.
"CALL Hello.00F71040"에서 마우스 우클릭을 누르고 Follow를 통해 main함수로 진입한다.
main 함수에서 각 줄별로 어셈블리어 명령어 행위에 대한 설명을 주석으로 정리했다. [그림 4]에서 주석 작성 공간에 마우스로 클릭하여 ;을 치면 주석을 작성할 수 있다.
[그림 5]에서 ASCII 코드에 hello world라고 나타난 부분의 주소는 001F3000임을 확인할 수 있다.
[ 명령어의 의미 - Hello.exe ]
001F1040 /$ 55 PUSH EBP ; 프롤로그 - 스택의 처음 위치 설정
001F1041 |. 8BEC MOV EBP,ESP ; 프롤로그 - 스택의 마지막 위치 설정
001F1043 |. 68 00301F00 PUSH Hello.001F3000 ; Arg1 = 001F3000 ASCII "Hello World"
001F1048 |. E8 13000000 CALL Hello.001F1060 ; Hello.001F1060
001F104D |. 83C4 04 ADD ESP,4 ;
001F1050 |. 33C0 XOR EAX,EAX ; return 0;
001F1052 |. 5D POP EBP ; 에필로그 - 스택의 처음 위치 해제
001F1053 \. C3 RETN ; 에필로그 - 함수를 호출한 지점으로 돌아감
위에서 분석한 내용을 바탕으로 Hello.exe의 C언어 코드를 작성했다.
1. 각 프로그램을 한 줄씩 어셈블리어 명령어 행위 작성
IN_OUT.exe 파일의 main 함수에 들어가서 어셈블리어 명령어 행위를 한 줄씩 분석했다.
[ 스택 조작 명령어 ]
- PUSH oper1 : oper1을 스택에 저장
- POP oper1 : 스택의 제일 위에 있는 값을 빼서 oper1에 저장
- MOV/MOVSX oper1, oper2 : oper2의 값을 oper1에 저장 (MOVSX는 oper2가 음수일 때 사용)
- LEA oper1, oper2 : oper2의 주소를 oper1에 저장
- CALL oper1 : oper1 주소 호출
- RET/RETN oper1 : 이전에 호출된 주소로 되돌아감
- ADD oper1, oper2 : oper1에 oper2를 더한 뒤 결과 값을 oper1에 저장
- SUB oper1, oper2 : oper1에서 oper2를 빼고 결과 값을 oper1에 저장
- MUL/IMUL : MUL은 부호 없는 곱셈 명령 수행 / IMUL은 부호 있는 곱셈 명령 수행
- DIV/IDIV : DIV은 부호 없는 나눗셈 명령 수행 / IDIV은 부호 있는 나눗셈 명령 수행
- INC oper1 : oper1의 값이 1만큼 증가
- DEC oper1 : oper1의 값이 1만큼 감소
- AND oper1, oper2 : oper1와 oper2의 비트 AND 연산 후 결과 값을 oper1에 저장
- OR oper1, oper2 : oper1와 oper2의 비트 OR 연산 후 결과 값을 oper1에 저장
- XOR oper1, oper2 : oper1와 oper2의 비트 XOR 연산 후 결과 값을 oper1에 저장
IN_OUT2.exe 파일의 main 함수에 들어가서 어셈블리어 명령어 행위를 한 줄씩 분석했다.
2. 어셈블리어 명령어의 의미 작성
[ 명령어의 의미 - IN_OUT.exe ]
00171080 /$ 55 PUSH EBP ; 프롤로그 - 스택의 처음 위치 설정
00171081 |. 8BEC MOV EBP,ESP ; 프롤로그 - 스택의 마지막 위치 설정
00171083 |. 51 PUSH ECX ;
00171084 |. 68 00301700 PUSH IN_OUT.00173000 ; "숫자를 입력하시오 : "를 스택에 저장
00171089 |. E8 32000000 CALL IN_OUT.001710C0 ; printf 함수 호출
0017108E |. 83C4 04 ADD ESP,4 ; 스택 정리
00171091 |. 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4] ;
00171094 |. 50 PUSH EAX ;
00171095 |. 68 18301700 PUSH IN_OUT.00173018 ; "%d"을 스택에 저장
0017109A |. E8 61000000 CALL IN_OUT.00171100 ; scanf 함수 호출
0017109F |. 83C4 08 ADD ESP,8 ; 스택 정리
001710A2 |. 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4] ;
001710A5 |. 51 PUSH ECX ;
001710A6 |. 68 1C301700 PUSH IN_OUT.0017301C ; "입력한 숫자는 %d입니다."를 스택에 저장
001710AB |. E8 10000000 CALL IN_OUT.001710C0 ; printf 함수 호출
001710B0 |. 83C4 08 ADD ESP,8 ; 스택 정리
001710B3 |. 33C0 XOR EAX,EAX ; return 0;
001710B5 |. 8BE5 MOV ESP,EBP ; 에필로그
001710B7 |. 5D POP EBP ; 에필로그 - 스택의 처음 위치 해제
001710B8 \. C3 RETN ; 에필로그 - 함수를 호출한 지점으로 돌아감 (종료)
IN_OUT.exe의 C언어 코드는 [그림 9]와 같이 나타낼 수 있다. 정수 변수 num의 이름은 임의로 지정했다.
[ 명령어의 의미 - IN_OUT2.exe ]
01181080 /$ 55 PUSH EBP ; 프롤로그 - 스택의 처음 위치 설정
01181081 |. 8BEC MOV EBP,ESP ; 프롤로그 - 스택의 마지막 위치 설정
01181083 |. 83EC 08 SUB ESP,8 ; 스택 정리
01181086 |. A1 48301801 MOV EAX,DWORD PTR DS:[1183048> ; 카나리 (메모리 보호기법)
0118108B |. 33C5 XOR EAX,EBP ; 카나리
0118108D |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX ; 카나리
01181090 |. 68 00301801 PUSH IN_OUT2.01183000 ; "문자를 입력"을 스택에 저장
01181095 |. E8 56000000 CALL IN_OUT2.011810F0 ; printf 함수 호출
0118109A |. 83C4 04 ADD ESP,4 ;
0118109D |. 68 0C301801 PUSH IN_OUT2.0118300C ; "하시오: "를 스택에 저장
011810A2 |. FF15 B0201801 CALL DWORD PTR DS:[<&api-ms-w> ; puts 함수 호출
011810A8 |. 83C4 04 ADD ESP,4 ;
011810AB |. 8D45 FB LEA EAX,DWORD PTR SS:[EBP-5] ;
011810AE |. 50 PUSH EAX ;
011810AF |. 68 18301801 PUSH IN_OUT2.01183018 ; "%c "을 스택에 저장
011810B4 |. E8 77000000 CALL IN_OUT2.01181130 ; scanf 함수 호출
011810B9 |. 83C4 08 ADD ESP,8 ;
011810BC |. 0FBE4D FB MOVSX ECX,BYTE PTR SS:[EBP-5] ;
011810C0 |. 51 PUSH ECX ;
011810C1 |. 0FBE55 FB MOVSX EDX,BYTE PTR SS:[EBP-5] ;
011810C5 |. 52 PUSH EDX ;
011810C6 |. 68 1C301801 PUSH IN_OUT2.0118301C ; "입력한 문자는 %c(아스키코드:%d)입니다.\n"을 스택에 저장
011810CB |. E8 20000000 CALL IN_OUT2.011810F0 ; printf 함수 호출
011810D0 |. 83C4 0C ADD ESP,0C ;
011810D3 |. 33C0 XOR EAX,EAX ; return 0;
011810D5 |. 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4] ; 카나리 (메모리 보호기법)
011810D8 |. 33CD XOR ECX,EBP ; 카나리
011810DA |. E8 8C000000 CALL IN_OUT2.0118116B ; 카나리
011810DF |. 8BE5 MOV ESP,EBP ; 에필로그
011810E1 |. 5D POP EBP ; 에필로그 - 스택의 처음 위치 해제
011810E2 \. C3 RETN ; 에필로그 - 함수를 호출한 지점으로 돌아감 (종료)
3. IN_OUT2.exe 오류 패치
[그림 9]를 보면 cmd 창에서 IN_OUT2.exe를 실행할 때 문자를 1번이 아닌 2번 입력해야 하고, 첫 번재로 입력한 문자의 ASCII 코드가 출력되는 오류가 있었다.
오류가 발생한 원인은 "%c "에서 c 뒤에 띄어쓰기가 되어 있어서였다. 25는 %를, 63은 c를, 20은 띄어쓰기를 가리키는 ASCII 코드 값이다. 띄어쓰기로 생긴 여백을 없애기 위해 ASCII 코드 값 20을 00으로 바꿔주어 패치를 하려고 한다.
우선 마우스 우클릭으로 View → Executable file 에 들어간다.
Executable file에서 마우스 우클릭한 후 Search for → Binary string 을 클릭한다.
Binary String에서 16진수 숫자 25 63 20을 입력한다.
25 63 20을 25 63 00으로 수정하기 위해 마우스 우클릭 후 Binary → Edit 으로 들어간다.
25 63 20에서 25 63 00으로 HEX+02 값을 수정한다.
수정한 값을 Save file로 저장하여 파일 이름을 IN_OUT2_patch.exe으로 했다.
IN_OUT2_patch.exe에 들어가면 25 63 00으로 값이 바뀐 것을 알 수 있다.
IN_OUT2_patch.exe를 실행했을 때 오류 패치가 정상적으로 완료된 모습이 나타난다.
- Total
- Today
- Yesterday
- c언어
- 컴파일
- Screen 객체
- DOM
- stdio.h
- 자료형
- keyword
- Document Object Model
- short
- 키워드
- bom
- int
- location 객체
- 리액트 #React #props #state #javascript
- Browser Object Model
- gcc
- long
- 변수
- window 객체
- Char
- Navigator 객체
- History 객체
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |