비쥬얼스튜디오와  

http://www.immunityinc.com/products/debugger/

이뮤니티 디버거를 다운받는다.



처음에 비쥬얼 스튜디오를 설정해주어야 한다.

프로젝트를 오른쪽 클릭하여 속성에 들어간다.




링커 - 고급 -임의기준 주소를 '이미지를 임의로 선택하지 않습니다.' 




일반-문자 집합 - '설정안함' 체크





최적화- 최적화 -'사용 안함' 체크





다음은 간단한 c파일을 생성하자


#include<stdio.h>

int main() {

printf("Hello World!");

return 0 ;

}


언어책 가장 먼저 피면 나오는 헬로우 월드 출력문이다.

이 파일을 디버깅 말고 릴리즈로 컴파일을 하자


릴리즈한 파일은

내 문서-Visual Studio [년도]-Project -[프로젝트이름]-Relese-[파일이름]

에 있다.




릴리즈로 컴파일이 끝났다면 이 파일을 이뮤니티 디버거에서 열어본다.

다음과같은 알 수 없는 어셈블리어들이 존재하지만 겁먹지 말자.


오른쪽 클릭해서 View-[릴리즈한 파일 이름] 을 클릭해서 main함수를 콜하는

CALL [파일이름].main 에 f2를 눌러서 브레이크를 걸어주자.

브레이크가 걸리면 f9를 눌러서 진행할 때, 그쪽에 자동으로 멈추게된다.

f2로 브레이크를 걸었다면 f7로 들어가서 main함수를 자세히 살펴보자



만약 찾지못하고 넘어갔을땐 Ctrl+F2로 다시 시작할 수 있다.



PUSH MOV..알수없는게 나오고 3번째 줄을보면 오른쪽에

format = "Hello World!" 라는 걸 볼 수있다.

기본적으로 가장 먼저 앞에 나오는 PUSH MOV ADD XOR 같은 것을

Mnemonic 이라고 한다.

어셈블리어는 Mnemonic [OP1] [OP2] 로 되어있다.

만약 ADD A,B 라면 A와 B를 더한값을 A에 저장해라 라는 뜻이다.


Push 바로 왼쪽을 보면 68 F4204000 이라고 써져있다.

또한 중요한 점이 있는데.


intel CPU는 메모리를 읽고 쓰는 주소를 거꾸로 해놓는다.

이것을 Little Endian 이라고 한다.


그리고 intel CPU는 Byte Machine이다.

여기서 Byte Machine은 메모리를 읽고쓰는 단위가 1바이트라는 뜻이다.


이 두개를 조합하면 F4204000이라는 주소값은 16진수이므로


2자리씩 끊어서 뒤로 읽어줘야 한다.


따라서 F4204000

004020F4 라는 주소가 된다.

이것을 이용해서 Hello World가 있는 주소값으로 가보도록 하자.
















크게 찍어놨는데 왼쪽위는 코드가 저장되어있는 메모리이다.

오른쪽 위는 레지스터의 값을 볼수 있는 창이다.

왼쪽 아래는 메모리 주소를 볼수 있는 창이다.

오른쪽 아래는 스택을 볼 수 있는 창이다.


왼쪽 아래에서 오른쪽 클릭을하여 Go To - Expression을 클릭하여서

방금 찾은 주소인 004020F4로 이동해보자




찾아보면 오른쪽에 Hello World!가 있는것을 확인 할 수 있다.





이제 F7를 한번 눌러 진행해보자. 진행할때 오른쪽 아래인 스택 메모리를 참조하자




한번 누르고..




한번 더누르니 스택값에 Hello World가 들어왔다.




f7을 누르니 mnemonic이 CALL이고 뒤에 보니 printf 를 호출하는것 같다고 이 tool이 얘기해준다.

그리고 f7을 누르면



이상한 주소값으로 가는데 놀라지말자. 여기는 printf의 영역이다.

printf는 내가 선언한 함수가 아니고 이미 선언되어 있는 것이므로 printf를 가져오는 과정이다.



스택메모리를 보면 올라온 것을 확인할 수 있다.

여기서 주목해야할 점은 Call to printf from hello.00401008 옆에있는

0040100E라는 주소값이다. 이 주소값은 함수가 CALL이 되었을 때, 어디로 주소를 복귀시켜야 하는지에 대한 설명이다.

CALL이 되어 printf에 들어가고 RETN을 만났을 때 0040100E라는 주소값으로 나온다는 뜻이다.





뭔가를 막 한다. F7를 눌러서 막 지나가다보면 RETN을 만난다. 

RETN을 만날때 까지가 printf 함수에 대한 내용이다.

여기서 F7을 눌러주면



아까 적혀진 0040100E로 돌아왔다.




그 다음 명령어인 ADD ESP,4에 대해 알아보자




오른쪽 위에 있는 레지스터메모리를 주목하자




ESP:현재 스택의 최상단 주소를알려준다

Extended stack pointer

EBP:현재 스택의 최하단의 주소를 알려준다

Extended Base Pointer

EAX,EBX,ECX,EDX ->범용 레지스터

필요할때 사용하는 레지스터이다.


또한 레지스터의 사이즈는 32비트이다 . 이것은 32비트 CPU라는 것을 의미한다.

64비트 CPU는 레지스터 크기가 64비트이다.



그렇다면 ADD ESP,4 는 

현재 스택 최상단 주소값에 4를 더하라는 뜻이다. 이말은 무엇이냐면

Hello World! 라는 문자열이 이제 더 이상 쓸모가 없으니 주소값을 4를 더해 

스택의 최상단을 한단계 위에있는 주소를 가르키도록 하는 것이다.

이 말은 즉 Hello World 값을 버리겠다는 뜻이다.


그 다음인 XOR EAX,EAX 은 무엇일까.















레지스터 값을 보면 EAX에 0000000C가 저장되어 있다.

똑같은 값에 XOR 연산을 하면 모두 0으로 변한다.


따라서 이 명령어는 EAX레지스터를 초기화 시키는 명령어가 되겠다.




EAX가 초기화 되었다.

여기서 알아두어야 할 점이 하나 더있다.

 여기서 나오는 MOV라는 함수는 MOVE가 아니라 Copy라는 뜻이다

MOV A,B 는 A에 있는걸 B에다가 Copy를 한다는 뜻이다.

그렇다면 MOV 를 이용하여서 EAX값을 0으로 초기화 시켜줄 수 있지 않을까?


어셈블리어는 기계어므로 기계한테는 비트연산이 훨씬 빠르다.

따라서 MOV를 사용하지않고 XOR를 사용하여 초기화 하는 것이다.

F7을 눌러서 Main함수의 RETN을 만나서 나오면




아까 브레이크를 걸어놨던 곳 바로 아래로 나오게 된다.





오른쪽 레지스터 값에 EIP를 확인해 보자

EIP는 다음 명령어의 주소를 적어논 레지스터 이다.

다음 명령어 주소인 0040117E가 적혀져있는것을 확인할 수 있다.


이제 응용하여 2가지 장난을 쳐보자.



1.화면에 FUOK YOO 표시하기 (Hello World 대신에)

2.MAIN 리턴하면 printf로 다시 돌아가서 Hello World를 두번 찍기





1. 화면에 FUOK YOO 표시하기.






아까 Hello World!가 저장된 주소를 가서, 글자 하나를 클릭하여 컨트롤+e를 누른다.

눌러서 unicode란에 하나 하나 바꿔줘보자.







그러면 Hello World!는 사라지고 바뀐 FUOK YOU!!가 보일 것이다.



2.Hello World 2번찍기





00401014 주소에 있는 RETN 값으로 F7을 눌러 이동한 뒤에 오른쪽 아래에있는 스택에 복귀주소를 바꿔준다.

0040117E라고 되어있는 주소를 Hello World! 를 PUSH하는 주소를 적어주면 된다.

00401003 을 적어주자.

그러면 RETN문이 끝나고 메인함수를 빠져나가지 않고 바뀐 복귀주소인 00401003으로 이동하여서 

Hello World!를 한번 더 찍게된다.






바꿔준다,. 오른쪽 클릭을 해서 Modify를 누르면 된다.





두번 찍힌 모습이다.

다음에는 scanf를 이용한 간단한 리버싱을 진행해보겠다.



+ Recent posts