############################################
미해결
임포트가 있는 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