2013-06-18 Lazly
목차 1. 목적 3 0x01. 문서의목적. 3 0x02. 문서에서다루는내용 3 2. 프로그램설명.. 4 0x01. AsProtect 설명. 4 3.... 5 0x01. Find OEP... 5 0x02. DUMP.. 7 0x03. 에러발생.. 9 0x04. 에러확인.. 11 4. 자동화기법. 14 0x01. 빈공간찾기. 14 0x02. 자동화코드설명 14 0x03. IAT 주소.. 16 0x04. Dump 파일에적용 16 5. 마무리. 19 2
1. 목적 0x01 문서의목적 문서의목적은본인이패킹된파일을 MUP을하면서가장재미있었던 Asprotect MUP을문서화시켜보려고합니다. 많은패킹된파일들을언패킹시켜본것은아니지만자동스크립트도통하질않았고, 문서들도전부외국문서였던패커는처음이었습니다. 다행이도아주설명이잘된문서가있어서몇일간의 ( 띄엄띄엄한달 걸린것같네요허허 ) 삽질끝에 MUP를할수있었습니다. 서두에밝히지만본문서는내가보고 MUP했던문서를초보자들이좀더보기쉽게접하길바라는마음에재해석하는문서입니다. 그렇기에본문서내용의저작권은원문서를작성하신그분께있습니다. ( 그분이라칭하는이유는 coolsoft에서받은문서인데 coolsoft의리뉴얼때문에누군지정확히모르겠습니다..) 0x02 문서에서다루는내용 본문서는언패킹에대해지식이조금있다는가정하에 Asprotect 2.1 ska를언패킹하는방법에대해설명하고자합니다. 부터시작해서왜 Asprotect MUP가안되었는지, 그리고어떻게해나가는지를순차적으로차근차근초보자에게맞춰서제작해보려고합니다. 3
2. 프로그램설명 0x01 Asprotect Asprotct 1.3 - > 2.x버전으로넘어오면서가장크게달라진점은 IAT 주소공간을제대로연결시켜주지않는다는큰특징이있습니다. 정확히는 AsProtect 내에서연결되지만, 패킹을풀어버리기때문에 IAT가제대로연결안되는것입니다. 결국에는 IAT를직접적으로다가져와서프로그램내에삽입을해주어야한니다. ` 본문서에서다룰 ASProtect 2.1 SKE 정보입니다. 4
3. 0x01. Find OEP Ollydbg 로 unaspack.exe 를실행시킨뒤 Options -> Debugging options -> Exceptions 탭에서설정합니다. Ollydbg 로실행시키면다음과같이익숙한화면으로넘어가게됩니다. AsPack 과마찬가지로 AsProtect 는실행되기바로이전까지실행시킨후메모리뷰에서 Code 영역에 Break 를걸어주는것이정석입니다.. F9 로진행시켜보겠습니다. 5
다음과같은화면이걸리고 Access vilation When writing to [00000000] use shift + f7/f8/f9 to pass exception to program 이걸림을확인할수있습니다.. Shift + F9 로실행되기바로직전까지의실행횟수를세보겠습니다. 즉 26 번째에실행이된다면바로 25 번째까지 shift + F9 를해주면된다는이야기입니다. 바로위에주소까지멈춤을확인할수있다. 필자컴퓨터기준으로 25 번의실행입니다. 이렇게까지실행을해준후 Ctlr + M 을눌러줘서 Code 영역에 Break Point 를걸어줍니다. Break Point 까지걸어준뒤에 Shift + F9 를해주면 OEP 를찾을수있다. 위의화면은패킹으로인해제대로 Code 가안보이는것입니다. 오른쪽버튼 -> Analysis -> Remove analysis from module 을해주면소스가제대로표시됩니다. 6
0x02. DUMP 오른쪽버튼 -> Dump debugged process 혹은 Plugins -> OllyDump -> Dump debugged process 의 옵션으로파일을 Dump 할수있습니다. Rebulid Import 의옵션을제거해준뒤에 Dump 버튼을눌러저장해줍니다.. Rebulid Improt 의경우 Ollydbg 자체에서지원하는 IAT 복구옵션입니다. 많은패치가이뤄져서성공률이꽤높다고하지만 본인의경우는 ImportREC 를쓰고있기에옵션을제거했습니다. 이렇게 Dump 파일까지만들어준뒤에 Ollydbg 를종료시키지않고바로 ImportREC 프로그램을실행 시킵니다. 7
보시는바와같이 Ollydbg 로실행되고있는 unasprske.exe 에붙을수있습니다. DUMP 했을때에 OEP 값을적어주고 AutoSerch 로 RVA 와 Size 를알아내고 Get Imports 를해줍니다. 하지만이프로그램역시확실하게값을구해주는것은아닙니다. IAT 값들을확실하게알수있는방법을알려드리도록하겠습니다. OEP 살짝아래부분을보면은 Kernel32 를 Call 하고있는부분이보인다. 바로 IAT 부분들이모여있는 부분임을추측할수있습니다.. DWORD PTR[42A250] 으로 Ctlr + G 로가보면좀더정확하게알수 있다. 8
IAT가있는것을확인할수있다. 그리고그주위를보면은 00 00 00 등이중간에껴있고여러값들여있는것을확인할수있다. 필자의경우검색을 2A000부터 2000을해주었습니다. 어차피범위검색이기때문에정확하지않아도됨으로, Import REC가제대로 RVA와 Size를잡아주지못하는것같다면은이런식으로검색해줍니다. 모두검색해준뒤에 Fix Dump 로 Dump 한파일에 IAT 를수정해줍니다. 0x03. 에러발생 정상적인 MUP 를수행을다한것이라면실행이되는것이정상이지만 AsProtect 의경우실행이 되지않고오류가뜹니다. 왜오류가나는것인지확인해보겠습니다. IAT 까지삽입한 DUMP 파일을실행시켰을때의에러창이다. 9
바로이부분에서에러가남을확인할수있다. 00402EBD E8 3ED17F00 CALL 00C00000 이주소는 Asprotect 2.1x SKE 가 IAT 를에뮬레이션해주어실행되던 HIMEM Call 입니다. 그럼이프로그램에서몇개의 HIMEM Call 이존재하는지알아봅시다. 오른쪽마우스 -> Search for -> All Commands 후 CALL 00C00000 을검색해봅니다. 꽤많은양의 HIMEM CALL 들이존재함을알수있습니다. 이렇게수많은 HIMEM CALL 들이프로그 램내 AsProtect 에서 IAT 를에뮬레이팅해주는것이다. 근데 AsProtect 패킹을언패킹했기때문에 10
IAT 를에뮬레이팅해줄수없어서에러가났었던것입니다. 0x04. 에러확인 우선적으로확인해야할사항은바로, Dump로뜬파일의 00402EBD E8 3ED17F00 CALL 00C00000 이부분에서에러가남을확인할수있습니다. 그렇다면언패킹되기전에저주소에는무엇이있을까와언패킹되기이전에저곳에서어떤일이벌어질것인가가확인해봐야할사항인것입니다. 무엇이 Wirte 되던지 Acess가되던지저곳을중심으로이뤄질것이기때문입니다. 초보자의입장으로쓴문서이기에한번생각할수있도록이야기를길게써두었습니다. 약 5 분정도어떻게접근해야할것인가생각하신다면은실력향상에적지않은도움이될것이라 예상됩니다. 패킹된파일을열고 Shift + F9 의작업을 25 번해줘서 OEP 를찾아주고, 에러가나는지점인 00402EBD 로가보겠습니다. CALL 00C00000 주소값옆에 E8 3ED17F00 의값이보일것이다. 바로이주소에 Hardware BP 를걸어 보도록하겠습니다. BP 를거는방법은다음과같습니다. E8 부터가아닌 50 부터걸게되는데, 이이유는 cpu 는 4 바이트씩값이움직이기때문입니다. 부득이하 게 E8 3ED17F00 의값이변경되는것을확인하려면은 4 바이트의첫번째부분에 BP 를주는것입니 다. 즉시나리오는이렇습니다. AsProtect 가전부진행되고, 마지막으로프로그램의 IAT 를에뮬레이팅해 줄것인데, 그에뮬레이팅해주는곳에 Wirte 로 Hardware BP 를걸어놓는다면은분명 IAT 가에뮬레이 팅될때멈추게될것입니다. 확인해보도록하겠습니다. Cltr + F2 로프로그램을다시실행시켜보도록하겠습니다. 11
30 번째의 Shift + F9 의진행으로다음과같은주소에 BP 가걸림을확인할수있었습니다. 그리고이주소바로위로가게된다면은다음과같은화면을볼수있을것입니다. CALL 문이 3 개있고, 아래에 JMP 문이있는이코드부분은 AsProtect 의전형적인 IAT 에뮬레이팅부 분이다. 버전마다조금씩다르겠지만대부분이런형태의코드를따르고있습니다. 첫번째 CALL 부분의바로위 MOV EDX, DWORD PTR [EBP-4] 부분을기억합니다. 다음과같이 Kernel32.GetStartupInfoA 를확인할수있다. 바로첫번째 IAT 를에뮬레이션해주는부 분인것입니다. 12
위의명령이실행되고 009BB848 JMP문으로오게된다면은해당 HIMEM CALL은 00402EBD E8 3ED17F00 CALL 00C00000 이렇게됩니다. 이렇게되었을때 Dump를뜨게되었을때에러가나게되는것입니다덤프파일에서 00402EBD E8 3ED17F00 Call kernel32.getstartupinfoa 되어야지에러가나질않습니다. 바로이곳에서 AsProtect 가 IAT 를에뮬레이션해주는부분이고이부분을수정한다면은모든 HIMEM CALL 에함수를직접입력해주고, 덤프를뜰수있게됩니다. 이프로그램에서처음에뮬레이션되는 IAT 는 7C801EF2 (kernel32.getstartupinfoa) 입니다. 이것을바로저부분에적용시켜보도록하겠습니다. MOV EAX, DWORD PTR [EBP-4] 에서 7C801EF2 를넣으니제대로잡히는것을볼수있습니다. 그리고 F9 로진행했을때 00C00000 의값이제대로 IAT 잡히는것을확인할수있습니다. 이모든작업을수동으로할수는없을것입니다. 자동화를시켜보도록하겠습니다. 이제수동으로이렇게잡은것을자동화시키는작업에대해알아보도록하겠습니다. 13
4. 자동화기법 0x01. 빈공간찾기 F2 로재실행후다음주소에 BP 를걸도록합니다. 첫번째 CALL 문바로위 MOV EAX, DWORD PTR [EAX+3C] 에 BP 를걸고빈공간을찾아보도록하겠 습니다. 빈공간을찾는이유는자동화소스를직접 삽입 하기위해서입니다. 쉽게예를들어새로운소스를직접삽입한후 JMP( 강제점프 ) 로그소스를실행하는것입니다. 가독성을높이기위해 9c2000 주소로소스를삽입하겠습니다. 0x02. 자동화코드설명 MOV EDX, DWORD PTR [EBP-4] 기억나시나요? IAT 가저장되어있는부분입니다. 때문에이곳에빈공간으로 JMP 해주는부분으로변경해줍니다. HIMEM CALL 을해주는부분역시강제로 JMP 문을변경해줍니다. 14
그뒤에 9c2000 에코드를삽입해줍니다. 덤프창에서더블클릭후오른쪽버튼으로복사를해주면됩니다. 복사해줄소스는다음과같습니다. 8B 40 3C 8B 55 FC 89 15 40 21 9C 00 50 A1 02 21 9C 00 83 C0 0A A3 02 219C 00 58 E9 E2 97 FF FF 00 00 00 00 8B 55 1C 42 89 15 46 21 9C 00 50 A1 24 21 9C 00 83 C0 0A A3 24 21 9C 00 58 89 02 E9 04 98 FF FF * 주의이명령어의경우작성자본인의환경에서만적용가능한것으로이문서를보시는분들은 약간의수정을하셔야합니다 삽입된코드입니다. 옆에주석으로짧게달았습니다. EBP-4에 IAT 값이저장되어있다는것을알고있기에 IAT 값을 edx에저장후그값을빈공간인 9C2140에저장합니다. 그리고원래주소로복귀하고, 마찬가지로 HIMEM Call 오프셋주소도빈공간에저장합니다. 그다음에이뤄지는작업들은다음 IAT를준비하기위한코드입니다. 15
0x03. IAT 주소 이렇게보기좋게저장됨을확인할수있습니다. 최종적으로뽑아낸 IAT 주소값들입니다. 이값을가지고 Dump 한파일에적용시키면되는거라 고여기까지오신분들은충분히예상하실수있습니다. 0x04. Dump 파일에적용 ASProtect 2.1x SKE 가모든해당 HIMEM Call 에에뮬레이션해주었던것을 덤프한파일에우리가만든코드를이용하여자동으로에뮬레이션해주도록하겠습니다. 올리로덤프한 dump.exe 를불러옵니다. 그리고또코드를삽입해줄것이니다음과같은빈공간을찾도록합니다. 찾은빈공간으로 JMP 문을처음 EP 부분에넣어줍니다. 이렇게해주면은총 5바이트를잡아먹어서그밑의부분의코드까지지워집니다. 다음은원본코드 5바이트어셈코드입니다. 004017B0 55 push ebp <=== 이곳을 jmp 00411F90 로수정하면 004017B1 8BEC mov ebp, esp 16
004017B3 6A FF push -1 <=== 이곳까지 5 바이트잡아먹습니다. 그렇기에 411F81 주소에붙여붙여넣습니다. 00411F80 0055 8B ; 엔트리포인터를점프로수정하기전값들 00411F83 EC ; 엔트리포인터를점프로수정하기전값들 00411F84 6A FF ; 엔트리포인터를점프로수정하기전값들 00411F86 0000 add byte ptr ds:[eax], al 00411F88 0000 add byte ptr ds:[eax], al 00411F8A 0000 add byte ptr ds:[eax], al 00411F8C 0000 add byte ptr ds:[eax], al 00411F8E 0000 add byte ptr ds:[eax], al 00411F90 51 push ecx ; 레지스터를사용하기위해원래값스택에보관 00411F91 56 push esi ; 레지스터를사용하기위해원래값스택에보관 00411F92 57 push edi ; 레지스터를사용하기위해원래값스택에보관 00411F93 mov ecx, dword ptr ds:[412003] ; 에뮬레이션해줄 IAT불러오기시작 00411F99 cmp dword ptr ds:[412003], 0 ; 에뮬레이션해줄 IAT가더없는가? 00411FA0 je short dump_.00411fe3 ; 끝이면 NP 복원코드로점프 00411FA2 sub ecx, dword ptr ds:[412009] ; 현재 IAT값을오프셋주소값을얻기위해변환 00411FA8 sub ecx, 4 ; IAT호출할주소를정확히얻기위해한번더빼줌 00411FAB mov esi, dword ptr ds:[412009] ; HIMEM Call 오프셋주소를 ESI로이동 17
00411FB1 mov dword ptr ds:[esi], ecx ; HIMEM Call에 IAT 복사 00411FB3 mov byte ptr ds:[esi+4], 90 ; HIMEM Call 오프셋주소르부터 5번째바이트 NOP으로 00411FB7 mov ecx, dword ptr ds:[411f95] ; 411F95 주소 4바이트값을 ECX 에넣고 00411FBD add ecx, 0A ; 다음 IAT를복사하기위해 10바이트뒤로이동 00411FC0 mov dword ptr ds:[411f95], ecx ; 10바이트이동된값을 411F95로복사 00411FC6 mov dword ptr ds:[411f9b], ecx ; 10바이트이동된값을비교하는루틴 411F9B로도복사 00411FCC mov ecx, dword ptr ds:[411fad] ; 411FAD가가르키는 HIMEM Call 오프셋주소를담고 00411FD2 add ecx, 0A ; 다음 HIMEM Call 오프셋주소얻기위해 10바이트뒤로이동 00411FD5 mov dword ptr ds:[411fa4], ecx ; 그런후 411FA4 주소에저장 00411FDB mov dword ptr ds:[411fad], ecx ; 411FAD 주소에도복사 00411FE1 jmp short dump_.00411f93 ; 찿아낸모든 IAT 에뮬레이션끝날때까지계속루프 00411FE3 mov esi, dump_.00411f81 ; NP 의원레값을 ESI에넣고 00411FE8 mov edi, dump_.<moduleentrypoint> ; NP 주소를 EDI에담은후 00411FED mov ecx, 5 ; ESI가가르키는주소부터 5바이트까지만 00411FF2 rep movs byte ptr es:[edi], byte ptr ds:[esi] ; 복원을시작한다. 00411FF4 pop edi ; 레지스터사용을다햇으므로원래값복원 00411FF5 pop esi ; 레지스터사용을다햇으므로원래값복원 00411FF6 pop ecx ; 레지스터사용을다햇으므로원래값복원 00411FF7 jmp dump_.<moduleentrypoint> ; NP로점프하면모든작업끝 다음은우리가만든전체코드를헥사로복사한것입니다. 이것을전부 411F81 번지부터복사해넣으시면됩니다. 55 8B EC 6A FF 00 00 00 00 00 00 00 00 00 00 51 56 57 8B 0D 03 20 41 00 83 3D 03 20 41 00 00 74 41 2B 0D 09 20 41 00 83 E9 04 8B 35 09 20 41 00 89 0E C6 46 04 90 8B 0D 95 1F 41 00 83 C1 0A 89 0D 95 1F 41 00 89 0D 9B 1F 41 00 8B 0D AD 1F 41 00 83 C1 0A 89 0D A4 1F 41 00 89 0D AD 1F 41 00 EB B0 BE 81 1F 41 00 BF B0 17 40 00 B9 05 00 00 00 F3 A4 5F 5E 59 E9 B4 F7 FE FF 마지막으로최종적으로 412003 주소에우리가얻은 IAT 와 HIMEM Call 값들을넣어주면은정상적으로 코드가작동하게되어서, 정상실행이됩니다. 전잘실행되네요. 여기까지 AsProtect 2.1 SKE 언패킹을마치도록하겠습니다. 18
5. 마무리 0x01. 끝으로.. Asprotect 2.1을언팩하면서많은외국문서들과, 외국자동스크립트를접했었는데제대로설명이안되어있다가 Cool soft에서어느분께서올려주신문서로겨우언팩할수있었습니다. 이자리를빌어그분께감사드린다고말씀드리고싶습니다. 끝으로서두에밝혔지만이문서의저작권 (?) 은그분께있음을다시한번말씀드립니다. 고작전문서를보기좋게한것뿐이없습니다. 고마운분의닉네임도몰라죄송합니다. ^^a 하하연락주시면제가고기사드리겠습니다!! 문서를끝까지읽어주셔서감사합니다 ~! 19