티스토리 뷰

Application/Debug

[해킹] Import Table

알 수 없는 사용자 2006. 6. 30. 10:38
Import Table

 


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


목적:


자 이번글에서는 프로그램에서 Import Table에 대하여


알아볼것이다. Import Table이란 프로그램이


Dll에서?Export 해주는 함수들을 동적 Import 해주는


집합?구조체이다. 이번 글을 알기위해서는


10번 RVA에 관한 강좌를 꼭 알아야만 한다.


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


타켓 파일: 다운받기


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


타켓 파일의 구조:










우선?PE 시그니처로 부터 0x80 의 위치에는??


Import Directory?의?RVA 값이 들어있다. 우리의


타겟 프로그램의?PE 시그니처는 0xB9 임으로


0xB9+0x80=0x139 부터 Import Directory?의 RVA


값이 있다는 것을 알수 있다.





위의 그림을 보면 0x139 의 위치에 있는 값이


50 20 00 00 인것을 알수 있다. 이는 RVA 값


0x2050을 뜻한다. RVA 0x2050은 FileOffset


0x850 이다. 0x850으로 가보자.





FileOffset 0x850즉 Import Directory에는 다음과 같은


값들이 들어있다. 이 값들은 0x14개씩이 한개의


Image_Import_Descriptor?이다.?우리의 타겟?프로그램


에는?0x850 부터?0x863 까지?첫번쨰 Ima_Imp_Des


이고 0x864 부터 0x877 까지 두번쨰 Ima_Imp_Des


0x878 부터 0x88B 까지가 세번쨰 Ima_Imp_Des 이며


마지막 0x88C 부터 0x89F 까지의 0x14만큼의?00은


Import Directory의 끝을 알리는 것이다.따라서 우리의


타겟 프로그램은 3개의 DLL에서 함수를 Import 하여


쓰고 있다는 말이 되는것이다.


Image_Import_Descriptor?의 구조는 밑과 같다.


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


0x0~0x3????:? Dword?? OriginalFirstThunk


0x4~0x7????:??Dword?? TimeDateStamp


0x8~0xB??? : ?Dword?? ForwarderChain


0xC~0xF??? :??Dword?? Name


0x10~0x13 :? Dword?? FirstThunk


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


여기서 TimeDateStamp 와 ForwarderChain은 00으로


셋팅하여 주며 Name은 DLL의 이름이 있는 주소의


RVA값이 들어있다.OriginalFirstThunk?나 FirstThunk는


Image_Thunk_Data의 시작지점의 RVA값이 들어있다.


우선 첫번쨰Ima_Imp_Des의 Name은 무언지 알아보자




0x850+0xC=0x85C~0x85F 이 Name 값인데

CA 21 00 00 이란 값이 들어 있음을 볼수 있다.


이는 RVA 0x21CA 를 뜻한다. RVA 0x21CA를


FileOffset으로 나타내기 위해 다음과 같은 식을 사용?


RVA(0x21CA)-VirtualOffset(0x2000)+RawOffset(0x800)


즉 FileOffset은 0x9CA 임을 알수있다.





위의 그림과 같이 0x9CA의 위치에는 user32.dll 이라는


것을 확인할수 있으며 이와 같은 방법으로 두번째


Ima_Imp_Des의 Name은 0xA0A 즉 kernel32.dll 이고


세번쨰 Ima_Imp_Des은 0xA26 즉 gdi32.dll 이라는


사실을 알수있다.


이제 두번쨰 OriginalFirstThunk 또는 FirstThunk가


포인트 하는 Image_Thunk_Data에 대하여 알아보자.


우선 위에서 왜또는이라는 말을 썻는가 하면 가끔 보면


OriginalFirstThunk의 값이 00 으로 셋팅된것을 볼수있다


그럴떄는 FirstThunk에 Image_Thunk_Data의 RVA값이


들어 있다는 것을 알아두자.





위의 그림은 첫번쨰 Ima_Imp_Des의 OriginalFirstThunk


값이 B8 20 00 00 임을 보여준다. 이는 RVA 0x20B8


로서 FileOffset으로 바꾸어 주기 위해 밑에 식을 사용


RVA(0x20B8)-VirtualOffset(0x2000)+RawOffset(0x800)


위 식을 사용하여 RVA 0x20B8의 FileOffset값 0x8B8


즉 Image_Thunk_Data의 시작지점을 알수 있다.





위의 그림에서 보듯이 0x8B8 부터 13개의 RVA값들이


들어 있고?이 RVA들은 각각?Image_Import_By_Name


의?위치를 가르키는?RVA값들이다. 맨끝 부분에는


Image_Thunk_Data의 끝을 알리는 1Word의 00으로


Image_Thunk_Data는 이루어져 있다.첫번쨰 RVA가


가르키는Image_Import_By_Name가 무언지 알아보자.


36 21 00 00 은 RVA 0x2136을 의미한다. 이를


FileOffset으로 바꾸어주면 0x2136-0x2000+0x800


=0x936이 된다.





위의 그림에서 보듯이 FileOffset 0x936 에는 Word 값의


Hint 값, Import 할?함수 이름 그리고 끝을알리는 00 으로


이루어져있음을 볼수있다.


Image_Import_By_Name 의 구조는 밑과 같다.


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


0x0~0x2????:? Word???? ?Hint


0x3~0x???? :? String???? Name


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


어떤떄는 Name이 00으로 셋팅되어 있을떄가 있다.


이럴떄는 Hint 값을 통하여?함수 가 Import 되는것이다.


자 지금까지 우리는 Import Table의 구조에 대하여


알아보았다. 저는 이제 위에의 내용을 응용하여


프로그램에 새로운 함수를 Import 시키는 방법에


대해서 적을것이다.이미 이 기능을 하는 툴은?있으며


한번 알아보는 것이 좋음으로 한번 읽어 보자.


보다 시피 우리의 타겟 프로그램 의 IAT에는 새로운


Image_Import_Descriptor를 추가 시킬 공간이 없다.


이럴떄는 IAT의 위치를 옮기어 주면 된다.


우리의 IAT는 0x850 ~ 0x88B 까지이다.


이를 밑의 그림처럼 복사하여 준다.





그런 다음 Stud_PE 같은 PE파일에 섹션을 추가시킬수 있

는툴을 사용하여 해더를 추가하여 준다.





저는 위와 같이 0x300 크기의 섹션을 추가하였습니다.


우리가 새로 추가 시킨 섹션의 처음 시작지점(RawOffset)


이 0x1400이고 0x1400 부터 0x300 까지인 16FF 까지가


우리가 새로 추가시킨 색션의 크기 입니다. 이제?새로


추가 시킨 섹션에?0x3C 만큼의?IAT를 복사하여 넣을


것이기 떄문에?여기서 0x3C만큼을 밑처럼 삭제해 줍니다


 



그런 다음 0x1400 부터 밑처럼 IAT를 복사하여 넣습니다.





이제 PE해더에 기록되있는 ?IAT의 위치 RVA를 변경해


주어야 합니다. 우리의 타겟에 PE시그니처는 0xB9


인데 이 RVA는 PE시그니처로부터 0x80뒤에 있음으로


0xB9+0x80=File Offset 0x139에 IAT 위치에 대한 RVA


가 기록되어 있다. 0x139에는 다음과 같이 되어 있다.





50 20 00 00 은 RVA 0x2050 임으로 이것을 FileOffset


으로 변경시키면 0x2050-0x2000+0x800=0x850 이


기록되 있음을 알수있다. 이것을 우리가 IAT를 옮긴


위치인 FileOffset 0x1400으로 옮겨 주어야 한다.


0x1400-0x1400+0x5000=0x5000 이 우리가 IAT를


옮긴 FileOffset 0x1400의 RVA 값인것이다. 이제


50 20 00 00 을 00 50 00 00 으로 바꾸어 준다.



자 위의 내용을 저장하고 파일을 실행해 봅시다.


정상적으로 실행되는걸 보실수 있을겁니다.


(실수만 하지 않았다면 말이죠) 이제 새로운 함수


를 추가시켜 보죠. 어떤 함수를 추가할까 생각해


보았지만 마땅히 떠오르는게 없어서 그냥


MessageBoxA를 추가시켜 보도록 하겠습니다.


MessageBoxA는 User32.dll 에 속하는 Dll 임으로


User32.dll 을 Name으로 하는 하나의 새로운


Image_Import_Descriptor을 추가시키어 보자.


(Image_Import_Descriptor?의 구조는 강좌의 상단부 참조)



위에처럼 Image_Import_Descriptor?를 추가시키어


주었습니다. 이대로 저장하고 프로그램을 실행하면


에러가 납니다.IAT의 사이즈가 틀려졌기 떄문이죠.


PE해더에 있는 IAT사이즈 값을 수정하여 주어야 합니다.


IAT사이즈는 PE시그니처로부터 0x84위치에 존재한다.


0xB9+0x84=FileOffset 0x13D에?IAT의 사이즈가 들어있다.





위 처럼?0x13D에는 50 00 00 00 이란 값이 들어 있었다.


한개의 Image_Import_Descriptor는 0x14의 크기를 가짐


으로 3개의 DLL의 Image_Import_Descriptor 과 끝을 알리는


빈 0x14 Image_Import_Descriptor 를 합치어서 0x50이란


값이 되는것인데 우리는 하나의 Image_Import_Descriptor를


더 추가 시키어 주었음으로 이값을 0x64로 수정시키어 준


다.이로써 실수한바만 없다면 성공적으로 MessageBoxA를


프로그램에 Import 시킨것이다. 이제 Import 시켰으니 이를



쓰기 위해선 어떻게 해야할까? 밑은 MessageBoxA의 원형이다.
int MessageBoxA(핸들,문자열,제목,타입);

이는 밑과 같다.?


::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


Push 타입????????????? ;스택에 타입집어넣음


Push 제목????????????? ;스택에 제목집어넣음


Push 문자열?????????? ;스택에 문자열 집어넣음


Push 핸들????????????? ;스택에 핸들 집어넣음


Call?MessageBoxA의 Import_By_Name?의 주소


::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


이에 대한것은 나중에 쓰도록 하죠. 지금은 시간이


없어서.:p 그럼 다음에 다시...Bye?


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


 


출처: http://dualpage.muz.ro/