############################################
미해결 임포트가 있는 Asprotect의 해법입니다.
############################################
대상 : 입문용+
타겟 : Advanced PDF Password Recovery Pro (http://www.elcomsoft.com/apdfpr.html) or here
도구 : Soft-Ice 4.x
Ice-Dump
Pe-Editor
ImportRec & Revergine 1.3
Hiew 6.x (핵스 에디터)
안녕하세요? 언팩킹에 재미 좀 붙이셨는지요? 이번엔 미해결 임포트가 있는 경우를 다루어 보겠습니다. 그리고 강좌의 맨 마지막에는 IAT의 원리에 대해서 설명해보려 합니다. 이번에 다룰 것 역시 Asprotect 1.2x입니다. 하지만 같은 1.2x 버전이라고 해서 난이도가 같지는 않습니다. 그럼 숨 크게 들이쉬시고 저와 함께 가보시죠!
1. Pe-Scan으로 확인해보면 Asprotect라고 나온다.
2. OEP를 찾을 차례입니다. 방법은 앞의 두 강좌에서와 동일하다. 우선 Bpx GetModuleHandleA Do "p ret"를 사용해 프로그램 내부로 들어간다. F5를 한번 누르면 다음처럼 나올 것이다.
0167:0065B074 FF95EC314400 CALL [EBP+004431EC]
0167:0065B07A 8985DC304400 MOV [EBP+004430DC],EAX
0167:0065B080 8BF8 MOV EDI,EAX
0167:0065B082 8D9DED304400 LEA EBX,[EBP+004430ED]
그럼 TraceX의 상한선을 정해보자.
:map32 apdfprp
Owner Obj Name Obj# Address Size Type
APDFPRP 0001 016F:00401000 0004A000 IDATA RW
APDFPRP 0002 016F:0044B000 00002000 IDATA RW
APDFPRP 0003 016F:0044D000 0000A000 IDATA RW
APDFPRP 0004 016F:00457000 0000E000 IDATA RW
APDFPRP 0005 016F:00465000 00006000 IDATA RW
APDFPRP .rsrc 0006 016F:0046B000 00017000 IDATA RW
APDFPRP shrek 0007 016F:00482000 00010000 IDATA RW ;이 색션의 이름이 좀 웃기네요 WoW
APDFPRP .adata 0008 016F:00492000 00001000 IDATA RW
음. 다행히도 사이즈가 그리 크지 않다.
/TraceX 401000 46B000
그리고 느긋하게 기다리자. 나의 시스템에선(MMX 233, 48RAM) 대략 30분 정도가 걸린다. 아마 여러분의 컴퓨터에선 5분이상 걸리지 않을 것이다. 기다림의 끝에 다음과 같은 화면이 뜬다.
0167:00401014 C3 RET
0167:00401015 C6B151A08C820A MOV BYTE PTR [ECX+828CA051],0A
0167:0040101C 2845C3 SUB [EBP-3D],AL
0167:0040101F D304B6 ROL DWORD PTR [ESI*4+ESI],CL
0167:00401022 A2E0424855 MOV [554842E0],AL
0167:00401027 2294D12F8E3E9A AND DL,[EDX*8+ECX+9A3E8E2F]
0167:0040102E D2E6 SHL DH,CL
0167:00401030 40 INC EAX
0167:00401031 AA STOSB
0167:00401032 40 INC EAX
0167:00401033 90 NOP
0167:00401034 C20CC3 RET C30C
매번 강조하지만 여긴 OEP루틴이 아니다. 다시 명령을 내리고 느긋하게 기다리자. 그러고 나면
--------------------------------------------------------------------------------
EAX=0041B024 EBX=005C0000 ECX=815EFC74 EDX=815EFCB4 ESI=815EFC54
EDI=00000000 EBP=0060FF78 ESP=0060FE3C EIP=0041B024 o d I s z a P c
CS=0167 DS=016F SS=016F ES=016F FS=45F7 GS=0000
--------------------------------------------------------------------------------
0030:00046500 674D7440 A82C438A 66457508 085B8B67 @tMg.C,..uEfg.[.
0030:00046510 75DB0B66 6739EBDE A833438A 67317501 f..u..9g.C3..u1g
0030:00046520 891C438B 8B67FE46 46891E43 FA468BFC .C..F.g.C..F..F.
0030:00046530 03D20603 7CFE463B F8468B17 03D40603 ....;F.|..F.....
0030:00046540 7CFC463B D38B660B 10EAC166 03EBC38B ;F.|.f..f.......
0030:00046550 C999C033 900004CA 66EC8B55 87B81E56 3.......U..fV...
0030:00046560 66D88E16 0B6C36FF 0676FF66 006A006A ...f.6l.f.v.j.j.
--------------------------------------------------------------------------------
0167:0041B024 E917060000 JMP 0041B640 (JUMP )
0167:0041B029 0310 ADD EDX,[EAX]
0167:0041B02B 40 INC EAX
0167:0041B02C 005741 ADD [EDI+41],DL
0167:0041B02F 54 PUSH ESP
0167:0041B030 43 INC EBX
0167:0041B031 4F DEC EDI
0167:0041B032 4D DEC EBP
0167:0041B033 20432F AND [EBX+2F],AL
0167:0041B036 43 INC EBX
0167:0041B037 2B2B SUB EBP,[EBX]
0167:0041B039 3332 XOR ESI,[EDX]
0167:0041B03B 205275 AND [EDX+75],DL
0167:0041B03E 6E OUTSB
0167:0041B03F 2D54696D65 SUB EAX,656D6954
0167:0041B044 207379 AND [EBX+79],DH
0167:0041B047 7374 JAE 0041B0BD
0167:0041B049 656D INSD
0167:0041B04B 2E2028 AND CS:[EAX],CH
0167:0041B04E 6329 ARPL [ECX],BP
----------------------------------APDFPRP!+0001A024-----------------------------
WINICE: Free16 Sel=3B47
ICEDUMP: LOG: CS:EIP: 0167:00664A2A, SS:ESP: 016F:0060FE3C, R0TCB: C99C9A10
ICEDUMP: LOG: instruction count: 00000000:03A5F284, R0TCB: C99C9A10
바로 이곳이 대망의 OEP이다. 무슨 jmp명령이 OEP냐고 생각하실 분이 계실 것 같아 설명을 덧붙여보자. 명령창에 나타난 로그를 살펴보자. 664A2A에서 점프해왔다고 적혀있다. 그럼 U 664A2A 해보자. 다음처럼 나올 것이다.
0167:00664A29 61 POPAD
0167:00664A2A FFE0 JMP EAX
어라 이것이 무엇인가? 바로 OEP로 점프하는 전형적인 루틴인 것이다. 거의 모든 UPX버전이 이렇게 점프하고 Asprotect의 많은 녀석들도 이런식으로 OEP로 점프한다. 흠 그럼 OEP를 적어두고 다음 단계로 넘어가자.
3. 쌔끈하게 덤프를 해보자. 이미지 사이즈는 93000이다. 따라서
/Dump 400000 93000 c:\pdf_Dump.exe
라고 명령을 내리시면 되겠다.
4. 이제 에디터로 적절하게 수정을 하자.
5. IAT를 리빌드 할 차례이다. 여느때와 같이 ImportRec를 띄워서 필요한 정보들을 수집해보자. 아마 하나의 미해결 임포트를 제외하곤 모두 풀릴 것이다. 덤프한 파일에 덮어씌우고 실행을 시켜보자.
6. 근데 허거덩. 에러가 나리라고 예상은 했지만 뭔가 이상하다. 자자 소프트 아이스를 띄우고 faults on 명령을 주고 닫자. 이 명령은 미리 할당되지 않는 메모리에 접근하려고 할 때 발생하는 에러를 잡아주는 것이다. Asprotect가 임포트 어드레스를 에뮬레이션 해줬는데, 만일 우리가 이녀석을 덤프하고 팩커 대신에 임포트 어드레스를 에뮬레이션 하는 가운데 미해결 임포트가 있다면, 그곳은 아마도 팩커의 영역이기 때문에 할당되지 않은 공간이 되어 에러가 발생하게 될 것이다. 뒤에서 자세하게 설명하겠으니 지금은 이정도로 넘어가자. 자 다시 실행해보면 아마도 여기에서 에러가 날 것이다.
65133C FFFF Invalid
그러면 당황하지 말고 r 을 누르자. r 을 누르면 명령입력이 가능해진다. 그리고 U *esp 해서 과연 어디에서 넘어왔는지 알아보자. 제 화면에선 이렇게 나오더군요.
--------------------------------------------------------------------------------
EAX=0060FE24 EBX=000000F4 ECX=0060FD30 EDX=0060FD30 ESI=0060FE24
EDI=0060FD30 EBP=0060FE2C ESP=0060FD14 EIP=0065133C o d I s Z a P c
CS=0167 DS=016F SS=016F ES=016F FS=40D7 GS=0000
-----DF_DUMP1_!+0760------------------------------------------------------------
0030:0044B760 0065133C 00665AF8 00665B04 00665B20 <.e..Zf..[f. [f.
0030:0044B770 00650EE8 00665B3C 00665B48 00665B58 ..e.<[f.H[f.X[f.
0030:0044B780 00665B70 00665B7C 00665B98 00665BB0 p[f.|[f..[f..[f.
0030:0044B790 00665BBC 00665BC8 00665BE4 00665BFC .[f..[f..[f..[f.
0030:0044B7A0 00651358 00665C10 00665C1C 00665C34 X.e..\f..\f.4\f.
0030:0044B7B0 00665C4C 00665C64 00665C7C 00665C8C L\f.d\f.|\f..\f.
0030:0044B7C0 00665C98 00665CA4 00665CC0 00665CF0 .\f..\f..\f..\f.
--------------------------------------------------------------------------------
016F:0041B9B2 2EFF1560B74400 CALL CS:[0044B760]
016F:0041B9B9 89C3 MOV EBX,EAX
016F:0041B9BB 89FA MOV EDX,EDI
016F:0041B9BD 31C0 XOR EAX,EAX
016F:0041B9BF E8B4FDFFFF CALL 0041B778
016F:0041B9C4 BAE40C4500 MOV EDX,00450CE4
016F:0041B9C9 FF15580C4500 CALL [00450C58]
016F:0041B9CF E84C2C0000 CALL 0041E620
016F:0041B9D4 89F0 MOV EAX,ESI
016F:0041B9D6 E8F5300000 CALL 0041EAD0
016F:0041B9DB B821000000 MOV EAX,00000021
016F:0041B9E0 E8C7200000 CALL 0041DAAC
016F:0041B9E5 FF15980C4500 CALL [00450C98]
016F:0041B9EB B8FF000000 MOV EAX,000000FF
016F:0041B9F0 E8B7200000 CALL 0041DAAC
016F:0041B9F5 5F POP EDI
016F:0041B9F6 5E POP ESI
016F:0041B9F7 59 POP ECX
016F:0041B9F8 5B POP EBX
016F:0041B9F9 C3 RET
----------------------------PDF_DUMP1_!+0001A9B2--------------------------------
Break due to Page Fault (0Eh). Fault=0004
:u *esp
:dd 44b760
어떤가요? [44B760]을 콜하니 에러가 납니다. 이 주소안을 보면 65133C라는 값이 있죠. 근데 에러가 난 것은 그다지 이상한 일은 아니나, 주변의 주소들을 살펴보면 모두 65xxxx으로 시작함을 볼 수 있습니다. 이 주소는 Asprotect의 주소이니, 현재 Asprotect가 에뮬레이션 해주고 있다는 얘기가 되겠군요. 그러나 우리가 덤프한 파일에는 Asprotect가 없으니 에러가 날 수 밖에요. 그런데 특이하게도 ImportRec가 찾아낸 것들을 보면 분명 제대로 찾긴합니다. 결국 IAT를 추가하는 과정에서 제대로 못해준 것 같습니다. 몇 번의 시도 끝에 포기하고 Revergine을 띄웠습니다. 그리고 동일한 방법으로 임포트를 복구했죠. 이때 미해결된 임포트가 6개 정도 나오는데, ImportRec에서 얻은 결과를 적용해주면 될 것입니다. 그럼 이제 이 파일을 가지고 에러를 잡아나갑시다.
가) 1번째 에러
에러가 뜨고 U *esp 입력하시면 다음과 같이 나올 것입니다.
0167:0041B85C Call [44b724]
그럼 44B724안의 주소를 살펴봅시다. dd 44B724 해주면 아마 65139C라고 나올 겁니다. 즉 다시말해 65139C에 있는 내용을 실행하겠단 얘기입니다. 그런데 현재 메모리가 할당되지 않아 FFFF라고 나오니 실행이 안되고 에러가 날 수 밖에요. 따라서 프로그램이 완전히 실행된 후에 이 주소에는 어떠한 값이 있었나 봐야겠습니다. 원본을 실행시켜주시고 bpx ShowWindow do "p ret"를 입력하시고 F5. 그리고 프로그램의 화면에서 Bench Mark라는 것을 눌러보세요. 아마 소아가 뜨면서 프로그램 내부로 들어갈 수 있을 겁니다. 주의하실 점은 쓸데없는 곳에도 걸릴 수가 있는데요. 이때는 F5를 눌러주시면서 빠져나가시면 되겠습니다. 반드시 어떠한 모듈에 걸렸는지를 확인하세요. 그리고 다음과 같이 명령을 줍시다
U 65139C
그럼 아마도 이렇게 나오겠죠.
--------------------------------------------------------------------------------
EAX=00000024 EBX=00620050 ECX=00463D94 EDX=81AC9062 ESI=00000000
EDI=00400000 EBP=0060FE2C ESP=0060FD0C EIP=0041B85C o d I s z A P c
CS=0167 DS=016F SS=016F ES=016F FS=0F87 GS=0000
--------------------------------------------------------------------------------
016F:00656CE4 04 0A 00 C0 FF FF FF 7F-00 00 40 00 D7 B6 FA FF .......�..@.....
016F:00656CF4 74 AE 5E 81 00 00 00 00-BC 7C 66 00 48 00 00 00 t.^......|f.H...
016F:00656D04 00 00 00 00 98 5A 66 00-00 00 00 00 00 00 00 00 .....Zf.........
016F:00656D14 00 00 00 00 00 00 00 00-00 00 00 00 FF FF FF FF ................
016F:00656D24 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................
016F:00656D34 FF FF FF FF FF FF FF FF-FF FF FF FF B2 FD 48 00 ..............H.
016F:00656D44 E9 7B 31 28 86 FA 0A FE-C4 88 C8 D7 1F A2 7C F5 .{1(..........|.
--------------------------------------------------------------------------------
0167:0065139C 6A00 PUSH 00
0167:0065139E E8B53DFFFF CALL KERNEL32!GetModuleHandleA
0167:006513A3 FF35E46C6500 PUSH DWORD PTR [00656CE4]
0167:006513A9 58 POP EAX
0167:006513AA 8B05F46C6500 MOV EAX,[00656CF4]
0167:006513B0 C3 RET
--------------------------------------------------------------------------------
:d 44b724
:u 65139c
:db 656ce4
보는순간 "요 녀석은 GetModuleHandleA구나"하고 생각하시기 쉽습니다. 하지만 그게 아닙니다. 확인해보는 방법은 call [44B724]를 call GetModuleHandleA로 바꾼후 실행해보면 되겠죠. 그러면 그다음 콜에서 이로인해 에러가 납니다. 결국 우린 위의 루틴을 어딘가에 복사하고 그리로 점프시켜야 합니다. 그리고 중요한 것은 656CE4와 656CF4에 담겨져 있는 값입니다. 이 값을 알려면 다시 실행해서 위 루틴으로 들어와 확인해봐야 합니다. 왜냐하면 프로그램이 완전히 실행된 후 확인하면 값이 변해있을 수 있기 때문이죠. 그렇다면 다시 실행해서 41B85C에 중단점을 설정합시다. 그런데 해보신 분들은 아시겠지만 여느 방식의 중단점을 설정하면 듣지를 않습니다. 걍 무시하고 바로 프로그램이 실행되죠. 저역시 고민하다가 다음과 같이 설정해보니 되더군요.
Bpr 41B85C 41B85D If (eip==0x41B85C) Do "U 41B85C"
이렇게해서 각각의 값을 알아낼 수가 있습니다. 위의 데이터 창을 참고하세요. 그럼 이제 이 값들을 우리가 원하는 아무 곳에나 복사해둡시다. 전 44B0F0번지에 넣었습니다. 한가지 주의할 사실은 그대로 넣으면 안되고 mov 명령에서 오퍼랜드의 주소가 달라지므로 기계어 코드도 변한다는 것입니다. 저 같은 경우에 656CE4의 값을 44B100에 넣고, 656CF4의 값을 44B110에 넣고 다음과 같이 작업했습니다.
0041B85C 6A 00 PUSH 0
0044B0F2 E8 9FC6B2BF CALL KERNEL32.GetModuleHandleA
0041B863 FF35 10B14400 PUSH DWORD PTR DS:[44B110]
0041B869 58 POP EAX
0041B86A A1 20B14400 MOV EAX,DWORD PTR DS:[44B120]
0041B86F C3 RETN
그럼 이제 Hiew(헥스 에디터)를 열어 위의 기계어코드를 그대로 옮겨 넣읍시다. 이제 남은 문제는 콜하는 녀석입니다. 사실 이부분을 제대로 말하자면 긴 설명이 필요한데요. 필요한 부분만 간추려서 설명드리겠습니다. 우선 call문을 고쳐서 44B0F0를 콜하게 하는 것은 현명한 방법이 못됩니다. 왜냐하면 말 그대로 임포트를 불러와서 사용하는 것이기 때문에 여기에서만 사용하는 것이 아니라 다른 곳에서도 사용할 수 있기 때문이죠. 따라서 이런 방식을 따른다면 아마 수십번도 넘는 곳에서 에러가 나고, 우리가 일일이 수정해줘야만 합니다. 그러니 임포트라는 것에 착안해서 65139C라는 주소를 44B0F0로 바꾸어 주면 되겠군요. 사실 간단해 보이나 한가지 간과한 사실이 있습니다. 하지만 문제가 되지 않으니 흐름을 위해 나중에 설명하도록 하죠.
나) 2번째 에러
--------------------------------------------------------------------------------
016F:0044B7D4 006513B4 BFF8220E BFF93507 BFF77E01 ..e.."...5...~..
016F:0044B7E4 BFFA1E03 BFFA1E26 BFF770B9 BFF9114E ....&....p..N...
016F:0044B7F4 BFFA2E28 BFF77A2E BFFA16B3 BFFC6190 (....z.......a..
--------------------------------------------------------------------------------
016F:0040765E 2EFF15D4B74400 CALL CS:[0044B7D4]
016F:00407665 89FB MOV EBX,EDI
016F:00407667 89C2 MOV EDX,EAX
바로 이곳입니다. 주소를 확인해보니 6513B4군요. 이것은 조금전의 미해결 임포트입니다. 사실은 임포트가 아니지만요. 아무튼 원본을 실행해서 원래 있어야 할 것이 무엇인지 보죠.
--------------------------------------------------------------------------------
016F:00656CF4 78 CE 5E 81 00 00 00 00-38 7B 66 00 48 00 00 00 x.^.....8{f.H...
016F:00656D04 00 00 00 00 14 59 66 00-00 00 00 00 00 00 00 00 .....Yf.........
016F:00656D14 00 00 00 00 00 00 00 00-00 00 00 00 FF FF FF FF ................
016F:00656D24 FF FF FF FF FF FF FF FF-FF FF FF FF FF FF FF FF ................
016F:00656D34 FF FF FF FF FF FF FF FF-FF FF FF FF B2 FD 48 00 ..............H.
016F:00656D44 E9 7B 31 28 86 FA 0A FE-C4 88 C8 D7 1F A2 7C F5 .{1(..........|.
016F:00656D54 50 F0 D6 4F B6 CB C9 50-19 14 61 7C D7 49 6F 72 P..O...P..a|.Ior
--------------------------------------------------------------------------------
0167:006513B4 55 PUSH EBP
0167:006513B5 8BEC MOV EBP,ESP
0167:006513B7 8B05F46C6500 MOV EAX,[00656CF4]
0167:006513BD 8B4508 MOV EAX,[EBP+08]
0167:006513C0 5D POP EBP
0167:006513C1 C20400 RET 0004
이것이군요. 이것 역시 위와 동일한 방법으로 할 수 있습니다. 전 다음과 같이 했습니다.
0044B130 55 PUSH EBP
0044B131 8BEC MOV EBP,ESP
0044B133 A1 40B14400 MOV EAX,DWORD PTR DS:[44B140]
0044B138 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
0044B13B 5D POP EBP
0044B13C C20400 RET 0004
그리고 이 녀석의 기계어 코드를 44B130에 기록했습니다. 그러니 6513B4를 44B130으로 바꾸어 줘야겠군요.
다) 마지막 에러
0167:407677 CALL [44B718]
이 44B718안에는 6513C4라는 주소가 있습니다. 역시 원본을 띄우고 확인해보면
0167:006513C4 55 PUSH EBP
0167:006513C5 8BEC MOV EBP,ESP
0167:006513C7 5D POP EBP
0167:006513C8 C20400 RET 0004
이렇게 나오죠. 처음엔 이 루틴을 보고 아무런 기능도 없는 루틴이라 생각하고 해당콜을 없애주려고 했으나, 위에서 언급했다시피 그렇게되면 수십군데를 고쳐주어야 하므로 이 루틴 역시 복사해서 새로이 만들어 주었습니다. 주소에 관계되는 어셈코드가 없으니 위의 코드를 그대로 옮겨심으면 되겠습니다. 전 44B150에 입력했습니다. 그리고 나서 6513C4라는 값을 44B150으로 바꾸어주었습니다.
자 이제 모든 에러가 잡혔습니다. 뿌듯한 기분으로 실행시켜 보세요. 아마 제대로 하셨으면 별탈없이 실행될 것입니다. 그럼 이제 번외 이야기를 하죠. 제 생각엔 아마도 IAT라는 것이 대체 무엇일까하는 분들이 많으실 것 같은데요. 사실 저도 잘 모릅니다. 하지만 제가 아는 한도내에서 설명드리죠. 우선 보시기전에 저의 PE관한 글을 아직 읽어보시지 않으신 분은 그것을 먼저 읽어보시길 권해드립니다.
앞에서 제가 설명을 하지 않은 부분이 왜 ImportRec로 IAT를 추가했을 때 에러가 났는지에 관한 것입니다. 저도 명확한 이유는 알 수 없지만 결과를 분석해봅시다. 우선 IAT 중 44B7D8을 가지고 설명해봅시다. 프로그램이 정상적으로 실행되었을 때, 이곳엔 MapViewOfFile의 주소인 BFF8220E가 있어야 합니다. 사실 Revergine으로 해줬을땐 이렇게 됩니다. 그런데 ImprotRec로 해줬을땐, 엉뚱한 주소가 들어가있습니다. 그리고 그 값이 66xxxx입니다. 즉 이것은 여전히 팩커가 IAT를 에뮬레이션 해줌을 뜻하는 거죠. 그러나 덤프한 파일엔 팩커가 없으니 당연히 에러가 날 수 밖에요. 이해가 잘 안가시는 분은 원본 프로그램을 실행하신뒤, 동일한 주소에 대해서 살펴보세요. 아마 주소가 66xxxx로 시작하며, 이 주소로 가보시면 어떤 함수가 있는지를 아실수 있을 것입니다.
그런데 특이하게도 헥스에디터를 열어 각각의 파일에서 44B7D8을 보면 두 개모두 665D0C라는 값이 들어있습니다. 왜 그럴까요? ImportRec는 그렇다치더라도 Rervergin은 제대로 된 값이 들어있어야 하는데 말이죠. 그런데 조금만 생각해보면 알 수 있습니다. 만약에 예를들어 위와 같은 임포트 리빌더로 알아낸 값들이 하드코딩된 형태로 들어간다고 생각해봅시다. 그러면 다른집 컴퓨터에선 실행이 안될 확률이 높음은 물론이며 DLL이 업그레이드 될 때마다 하드코딩된 주소를 다시 바꿔줘야만 합니다. 이 얼마나 번거로운 일입니까? 따라서 컴퓨터는 프로그램을 로딩하면서 동적으로 주소를 채워넣는 것입니다. 그래서 위에서 처럼 에러를 잡을 때 IAT를 하드코딩된 형태로 넣을 수 있는 것입니다. 어떻게 생각하면 상당히 모순된 이야기처럼 들리는데요. 그 원리는 이렇습니다. 만일 임포트 리빌더가 팩커가 에뮬레이션 해주는 것을 완벽하게 재현한다면 모든 IAT가 로딩될 때마다 채워지겠죠. 즉 우리가 하드코딩해서 넣은값은 무효가 되는 거죠. 하지만 임포트 리빌더가 위에서처럼 전혀 찾지를 못하거나 미해결 임포트로 남겨놓는다면, 이말은 임포트 리빌더가 IAT를 다시 쓰지 못한다는 것과 동일하죠. 왜냐하면 임포트 리빌더가 못해서 원래의 팩커역할로 남겨놓았는데 우리가 덤프한 파일엔 팩커가 없기 때문이죠.
마지막으로 임포트 리빌더의 도움을 받지 않고 어떻게 접근할 수 있나를 살펴보죠. 어디까지나 이해를 위한 것이지 이렇게 하실 필요는 전혀 없습니다. 우선 덤프한 파일을 faults on한 상태에서 실행한다. 그리고 에러가 나면 어디에서 불려왔는지를 확인한다. 대부분 call [xxxxxx]의 꼴로 나타난다. 혹은 call yyyyyy의 형태로 나타나는데, 이때 yyyyyy로 가보면 십중팔구 jmp [xxxxxx]로 나타나 있을 것입니다. 즉 call [xxxxxx]와 동일한 것이죠. 이때 xxxxxx가 바로 임포트할 함수의 주소를 담고 있는 곳이다. 이 IAT 영역을 잘 기억해둔다. 그리고 나서 원본 프로그램을 띄워 동일한 영역을 살펴본다. 그러면 아마 주소가 BFxxxxxx으로 시작하지 않고, 팩커의 주소로 나타나 있을 것입니다. 따라서 그 주소를 가보시면 대충 어떠한 함수가 있는지를 알 수 있죠. 데이터 창에 나타난 값들을 복사해서 기록해둡니다. 이 값을 덤프한 파일에 덮어쓴다. 그리고 기타 에러를 잡는다. 이렇게 하시면 아마 될 것입니다. 문제는 주소가 하드코딩된 형태로 들어가므로 배포가 어렵다는 것입니다.
끝입니다. 어떠신가요? 제 글솜씨가 부족해 다소 지루하셨으리라 생각됩니다. 하지만 직접 해보시면 아마 색다른 재미를 느끼실 수 있을 것입니다. 요즘들어 하는 생각인데 내가 왜 예전에 쉘코드 짜는 걸 힘들었했나하는 바보같은 생각을 합니다. 물론 윈도우용 쉘코드는 어렵지만 리눅스용은 그다지 어려운 것이 아니거던요. 지금에 와서 생각해보니 아마도 욕심만 앞서고 실제 해보지 않아서 그랬던 것 같습니다. 여러분들도 제글을 읽는 차원에서 머무르지 마시고 직접 해보심이 어떨런지요 *^^* 분명 훌륭하게 해내시리라 믿습니다. 허거덩 밤 꼴딱새고 아침 8시네요. 밥먹고 한숨 잘랍니다. 그럼 다음 강좌에서 보아엽 WoW
; Syntax for each function in a thunk (the separator is a TAB)
; ------------------------------------------------------------
; Flag RVA ModuleName Ordinal Name
;
; Details for <Valid> parameter:
; ------------------------------
; Flag: 0 = valid: no -> - Name contains the address of the redirected API (you can set
; it to zero if you edit it).
; - Ordinal is not considered but you should let '0000' as value.
; - ModuleName is not considered but you should let '?' as value.
;
; 1 = valid: yes -> All next parameters on the line will be considered.
; Function imported by ordinal must have no name (the 4th TAB must
; be there though).
;
; 2 = Equivalent to 0 but it is for the loader.
;
; 3 = Equivalent to 1 but it is for the loader.
;
; And finally, edit this file as your own risk! :-)
Target: C:\PROGRAM FILES\APDFPRP\APDFPRP.EXE
OEP: 00001000 IATRVA: 0004B000 IATSize: 000008EC
FThunk: 0004B4A4 NbFunc: 00000005
1 0004B4A4 advapi32.dll 00D8 RegCloseKey
1 0004B4A8 advapi32.dll 00DB RegCreateKeyA
1 0004B4AC advapi32.dll 00DC RegCreateKeyExA
1 0004B4B0 advapi32.dll 00F7 RegQueryValueExA
1 0004B4B4 advapi32.dll 0103 RegSetValueExA
FThunk: 0004B4BC NbFunc: 00000002
1 0004B4BC comctl32.dll 0011 InitCommonControls
1 0004B4C0 comctl32.dll 0010 CreateUpDownControl
FThunk: 0004B4C8 NbFunc: 00000001
1 0004B4C8 user32.dll 029F wsprintfA
FThunk: 0004B4D0 NbFunc: 00000008
1 0004B4D0 shell32.dll 00CD DragAcceptFiles
1 0004B4D4 shell32.dll 00CE DragFinish
1 0004B4D8 shell32.dll 00CF DragQueryFile
1 0004B4DC shell32.dll 0109 SHBrowseForFolder
1 0004B4E0 shell32.dll 011D SHGetMalloc
1 0004B4E4 shell32.dll 011F SHGetPathFromIDList
1 0004B4E8 shell32.dll 0142 ShellExecuteA
1 0004B4EC shell32.dll 0148 Shell_NotifyIcon
FThunk: 0004B4F4 NbFunc: 00000019
1 0004B4F4 gdi32.dll 0072 BitBlt
1 0004B4F8 gdi32.dll 0088 CreateCompatibleBitmap
1 0004B4FC gdi32.dll 0089 CreateCompatibleDC
1 0004B500 gdi32.dll 008A CreateDCA
1 0004B504 gdi32.dll 008F CreateDIBitmap
1 0004B508 gdi32.dll 0096 CreateFontIndirectA
1 0004B50C gdi32.dll 00A1 CreatePen
1 0004B510 gdi32.dll 00A5 CreateRectRgn
1 0004B514 gdi32.dll 00AA CreateSolidBrush
1 0004B518 gdi32.dll 00AD DeleteDC
1 0004B51C gdi32.dll 00B0 DeleteObject
1 0004B520 gdi32.dll 00FA GetDeviceCaps
1 0004B524 gdi32.dll 011A GetObjectA
1 0004B528 gdi32.dll 0129 GetStockObject
1 0004B52C gdi32.dll 0134 GetTextExtentPoint32A
1 0004B530 gdi32.dll 013A GetTextMetricsA
1 0004B534 gdi32.dll 0146 LineTo
1 0004B538 gdi32.dll 0149 MoveToEx
1 0004B53C gdi32.dll 0172 SelectClipRgn
1 0004B540 gdi32.dll 0173 SelectObject
1 0004B544 gdi32.dll 017A SetBkMode
1 0004B548 gdi32.dll 0192 SetPixel
1 0004B54C gdi32.dll 019C SetTextColor
1 0004B550 gdi32.dll 01A7 StretchBlt
1 0004B554 gdi32.dll 01AC TextOutA
FThunk: 0004B55C NbFunc: 00000003
1 0004B55C version.dll 0001 GetFileVersionInfoA
1 0004B560 version.dll 0002 GetFileVersionInfoSizeA
1 0004B564 version.dll 000C VerQueryValueA
FThunk: 0004B56C NbFunc: 00000059
1 0004B56C user32.dll 0007 AppendMenuA
1 0004B570 user32.dll 000C BeginPaint
1 0004B574 user32.dll 002E CharToOemA
1 0004B578 user32.dll 0033 CharUpperBuffA
1 0004B57C user32.dll 0036 CheckDlgButton
1 0004B580 user32.dll 003F CloseClipboard
1 0004B584 user32.dll 0049 CopyRect
1 0004B588 user32.dll 0051 CreateDialogIndirectParamA
1 0004B58C user32.dll 005C CreatePopupMenu
1 0004B590 user32.dll 005D CreateWindowExA
1 0004B594 user32.dll 0081 DefDlgProcA
1 0004B598 user32.dll 0087 DefWindowProcA
1 0004B59C user32.dll 008E DestroyIcon
1 0004B5A0 user32.dll 008F DestroyMenu
1 0004B5A4 user32.dll 0090 DestroyWindow
1 0004B5A8 user32.dll 0093 DialogBoxParamA
1 0004B5AC user32.dll 0095 DispatchMessageA
1 0004B5B0 user32.dll 00A5 DrawEdge
1 0004B5B4 user32.dll 00A8 DrawFrameControl
1 0004B5B8 user32.dll 00AA DrawIconEx
1 0004B5BC user32.dll 00A9 DrawIcon
1 0004B5C0 user32.dll 00AD DrawStateA
1 0004B5C4 user32.dll 00AF DrawTextA
1 0004B5C8 user32.dll 00B4 EmptyClipboard
1 0004B5CC user32.dll 00B7 EnableWindow
1 0004B5D0 user32.dll 00B9 EndDialog
1 0004B5D4 user32.dll 00BB EndPaint
1 0004B5D8 user32.dll 00D4 FillRect
1 0004B5DC user32.dll 00DD GetActiveWindow
1 0004B5E0 user32.dll 00E8 GetClassLongA
1 0004B5E4 user32.dll 00ED GetClientRect
1 0004B5E8 user32.dll 00F8 GetCursorPos
1 0004B5EC user32.dll 00F9 GetDC
1 0004B5F0 user32.dll 00FE GetDlgItem
1 0004B5F4 user32.dll 00FF GetDlgItemInt
1 0004B5F8 user32.dll 0100 GetDlgItemTextA
1 0004B5FC user32.dll 0103 GetFocus
1 0004B600 user32.dll 0104 GetForegroundWindow
1 0004B604 user32.dll 0117 GetMenu
1 0004B608 user32.dll 0125 GetMessageA
1 0004B60C user32.dll 0128 GetMessageTime
1 0004B610 user32.dll 0131 GetParent
1 0004B614 user32.dll 013E GetSysColor
1 0004B618 user32.dll 0141 GetSystemMetrics
1 0004B61C user32.dll 014E GetWindowDC
1 0004B620 user32.dll 0150 GetWindowLongA
1 0004B624 user32.dll 0155 GetWindowRect
1 0004B628 user32.dll 0157 GetWindowTextA
1 0004B62C user32.dll 0173 InflateRect
1 0004B630 user32.dll 017C InvalidateRect
1 0004B634 user32.dll 018C IsDlgButtonChecked
1 0004B638 user32.dll 0190 IsRectEmpty
1 0004B63C user32.dll 0196 KillTimer
1 0004B640 user32.dll 0197 LoadAcceleratorsA
1 0004B644 user32.dll 019B LoadCursorA
1 0004B648 user32.dll 019F LoadIconA
1 0004B64C user32.dll 01A1 LoadImageA
1 0004B650 user32.dll 01AF MapDialogRect
1 0004B654 user32.dll 01B7 MessageBoxA
1 0004B658 user32.dll 01C8 OemToCharA
1 0004B65C user32.dll 01CC OffsetRect
1 0004B660 user32.dll 01CD OpenClipboard
1 0004B664 user32.dll 01D9 PostMessageA
1 0004B668 user32.dll 01DB PostQuitMessage
1 0004B66C user32.dll 01E2 RegisterClassA
1 0004B670 user32.dll 01E3 RegisterClassExA
1 0004B674 user32.dll 01F1 ReleaseCapture
1 0004B678 user32.dll 01F2 ReleaseDC
1 0004B67C user32.dll 01F8 ScreenToClient
1 0004B680 user32.dll 01FC SendDlgItemMessageA
1 0004B684 user32.dll 0201 SendMessageA
1 0004B688 user32.dll 020A SetCapture
1 0004B68C user32.dll 020D SetClassLongA
1 0004B690 user32.dll 0210 SetClipboardData
1 0004B694 user32.dll 0217 SetDlgItemInt
1 0004B698 user32.dll 0218 SetDlgItemTextA
1 0004B69C user32.dll 021C SetForegroundWindow
1 0004B6A0 user32.dll 0239 SetTimer
1 0004B6A4 user32.dll 0240 SetWindowLongA
1 0004B6A8 user32.dll 0243 SetWindowPos
1 0004B6AC user32.dll 0245 SetWindowTextA
1 0004B6B0 user32.dll 0250 ShowWindow
1 0004B6B4 user32.dll 0257 SystemParametersInfoA
1 0004B6B8 user32.dll 0262 TrackPopupMenu
1 0004B6BC user32.dll 0265 TranslateAcceleratorA
1 0004B6C0 user32.dll 0268 TranslateMessage
1 0004B6C4 user32.dll 0274 UpdateWindow
1 0004B6C8 user32.dll 0296 WinHelpA
1 0004B6CC user32.dll 0299 WindowFromDC
FThunk: 0004B6D4 NbFunc: 00000067
1 0004B6D4 kernel32.dll 00A0 CloseHandle
1 0004B6D8 kernel32.dll 00B6 CreateEventA
1 0004B6DC kernel32.dll 00B9 CreateFileA
1 0004B6E0 kernel32.dll 00BA CreateFileMappingA
1 0004B6E4 kernel32.dll 00C6 CreateProcessA
1 0004B6E8 kernel32.dll 00CD CreateThread
1 0004B6EC kernel32.dll 00D6 DeleteCriticalSection
1 0004B6F0 kernel32.dll 00D8 DeleteFileA
1 0004B6F4 kernel32.dll 00E1 EnterCriticalSection
1 0004B6F8 kernel32.dll 00F8 ExitProcess
1 0004B6FC kernel32.dll 00F9 ExitThread
1 0004B700 kernel32.dll 0118 FindClose
1 0004B704 kernel32.dll 011C FindFirstFileA
1 0004B708 kernel32.dll 0121 FindNextFileA
1 0004B70C kernel32.dll 0123 FindResourceA
1 0004B710 kernel32.dll 0130 FreeEnvironmentStringsA
1 0004B714 kernel32.dll 0133 FreeLibrary
1 0004B718 kernel32.dll 0135 FreeResource
1 0004B71C kernel32.dll 0138 GetACP
1 0004B720 kernel32.dll 013E GetCPInfo
1 0004B724 kernel32.dll 01DC GetVersion
1 0004B728 kernel32.dll 014A GetCommandLineW
1 0004B72C kernel32.dll 0158 GetCurrentDirectoryA
1 0004B730 kernel32.dll 015A GetCurrentProcess
1 0004B734 kernel32.dll 015C GetCurrentThread
1 0004B738 kernel32.dll 015D GetCurrentThreadId
1 0004B73C kernel32.dll 015E GetDateFormatA
1 0004B740 kernel32.dll 016A GetEnvironmentStrings
1 0004B744 kernel32.dll 0177 GetFileSize
1 0004B748 kernel32.dll 0179 GetFileType
1 0004B74C kernel32.dll 0181 GetLastError
1 0004B750 kernel32.dll 0182 GetLocalTime
1 0004B754 kernel32.dll 0183 GetLocaleInfoA
1 0004B758 kernel32.dll 018B GetModuleFileNameA
1 0004B75C kernel32.dll 018C GetModuleFileNameW
1 0004B760 kernel32.dll 018D GetModuleHandleA
1 0004B764 kernel32.dll 0196 GetOEMCP
1 0004B768 kernel32.dll 0199 GetPrivateProfileIntA
1 0004B76C kernel32.dll 019F GetPrivateProfileStringA
1 0004B770 kernel32.dll 01A3 GetProcAddress
1 0004B774 kernel32.dll 01A6 GetProcessHeap
1 0004B778 kernel32.dll 01BB GetStdHandle
1 0004B77C kernel32.dll 01C2 GetSystemDirectoryA
1 0004B780 kernel32.dll 01C4 GetSystemInfo
1 0004B784 kernel32.dll 01CC GetTempFileNameA
1 0004B788 kernel32.dll 01CE GetTempPathA
1 0004B78C kernel32.dll 01D2 GetThreadPriority
1 0004B790 kernel32.dll 01D6 GetTickCount
1 0004B794 kernel32.dll 01D7 GetTimeFormatA
1 0004B798 kernel32.dll 01D9 GetTimeZoneInformation
1 0004B79C kernel32.dll 01DD GetVersionExA
1 0004B7A0 kernel32.dll 01DC GetVersion
1 0004B7A4 kernel32.dll 01E6 GlobalAlloc
1 0004B7A8 kernel32.dll 01ED GlobalFree
1 0004B7AC kernel32.dll 01F1 GlobalLock
1 0004B7B0 kernel32.dll 01F2 GlobalMemoryStatus
1 0004B7B4 kernel32.dll 01F7 GlobalUnlock
1 0004B7B8 kernel32.dll 020A InitializeCriticalSection
1 0004B7BC kernel32.dll 0215 IsBadReadPtr
1 0004B7C0 kernel32.dll 0228 LeaveCriticalSection
1 0004B7C4 kernel32.dll 0229 LoadLibraryA
1 0004B7C8 kernel32.dll 022E LoadResource
1 0004B7CC kernel32.dll 0230 LocalAlloc
1 0004B7D0 kernel32.dll 0235 LocalFree
0 0004B7D4 ? 0000 006513B4
1 0004B7D8 kernel32.dll 0249 MapViewOfFile
1 0004B7DC kernel32.dll 0251 MulDiv
1 0004B7E0 kernel32.dll 0252 MultiByteToWideChar
1 0004B7E4 kernel32.dll 0270 QueryPerformanceCounter
1 0004B7E8 kernel32.dll 0271 QueryPerformanceFrequency
1 0004B7EC kernel32.dll 027E ReadFile
1 0004B7F0 kernel32.dll 028E ResumeThread
1 0004B7F4 kernel32.dll 02B6 SetConsoleCtrlHandler
1 0004B7F8 kernel32.dll 02C1 SetCurrentDirectoryA
1 0004B7FC kernel32.dll 02C7 SetEnvironmentVariableA
1 0004B800 kernel32.dll 02C8 SetEnvironmentVariableW
1 0004B804 kernel32.dll 02CA SetEvent
1 0004B808 kernel32.dll 02CF SetFilePointer
1 0004B80C kernel32.dll 02D4 SetLastError
1 0004B810 kernel32.dll 02E0 SetStdHandle
1 0004B814 kernel32.dll 02EB SetThreadPriority
1 0004B818 kernel32.dll 02EE SetUnhandledExceptionFilter
1 0004B81C kernel32.dll 02F5 SizeofResource
1 0004B820 kernel32.dll 02F6 Sleep
1 0004B824 kernel32.dll 02FD TerminateProcess
1 0004B828 kernel32.dll 02FE TerminateThread
1 0004B82C kernel32.dll 0302 TlsAlloc
1 0004B830 kernel32.dll 0304 TlsFree
1 0004B834 kernel32.dll 0306 TlsGetValue
1 0004B838 kernel32.dll 0307 TlsSetValue
1 0004B83C kernel32.dll 0310 UnhandledExceptionFilter
1 0004B840 kernel32.dll 0314 UnmapViewOfFile
1 0004B844 kernel32.dll 0319 VirtualAlloc
1 0004B848 kernel32.dll 031B VirtualFree
1 0004B84C kernel32.dll 0320 VirtualQuery
1 0004B850 kernel32.dll 0325 WaitForMultipleObjects
1 0004B854 kernel32.dll 0327 WaitForSingleObject
1 0004B858 kernel32.dll 032B WideCharToMultiByte
1 0004B85C kernel32.dll 0336 WriteFile
1 0004B860 kernel32.dll 033B WritePrivateProfileStringA
1 0004B864 kernel32.dll 035A lstrcpyA
1 0004B868 kernel32.dll 0360 lstrlenA
1 0004B86C kernel32.dll 0361 lstrlenW
FThunk: 0004B874 NbFunc: 00000002
1 0004B874 comdlg32.dll 006E GetOpenFileNameA
1 0004B878 comdlg32.dll 0070 GetSaveFileNameA
'Hacking' 카테고리의 다른 글
DeFixed_Edition_v2 (0) | 2009.01.24 |
---|---|
How to Compile Wall Hack (0) | 2009.01.24 |
API & DLL (1) | 2009.01.24 |
W32DASM Disassembler (0) | 2009.01.24 |
Intro to Reverse Engineering-Part 2 (0) | 2009.01.24 |