You are on page 1of 12

//Armadillo v3.7X - v8.XX Debug Blocker / Standard / Minimum script //This script unpacks almost every version of Armadillo!

//It also unpacks UPX if it's detected... //Created by Mr. eXoDia // T.P.o.D.T 2011.26.04 //FOR USE OF RESEARCH ONLY! //Tested on the following versions (not //3.05 //3.10.???? (Custom Build!) (OEP-finder //3.70a //3.72 //3.77.0021 (Custom Build!) (OEP-finder //3.78.0194 (Custom Build!) (OEP-finder //4.00.0230 (Custom Build!) //4.00.0053 (Custom Build!) //4.10 //4.30a //4.40 //4.42 //4.44 //4.62 //4.66 //5.00 //5.02 //5.40Beta //5.40 //5.42 //6.05Alpha1 //6.40.0329 (Custom Build!) //6.60.0140 (Custom Build!) //6.62 //7.00Beta3 //7.00.0081 (Custom Build!) //7.05Alpha6b //7.20 //7.25Alpha9 //7.40 //8.00 //8.20 //8.40Beta1 //8.40 //8.60 all with UPX): ONLY!) ONLY!) ONLY!)

Armadillo byte signatures used: //#6800010000# = push 100 //#E8????????# = call XXXXXXXX //#5?# = push ? //#FFD?# = call [register] //#5F5253# = "_RS" //#3A53494D554C41544545585049524544# = ":SIMULATEEXPIRED" //--------------------------------------------------------------------------//

//Armadillo v4.xx - v8.xx CopyMem2 + IAT Elimination by:

//Mr. eXoDia // T.P.o.D.T 2011 //mr.exodia.tpodt@gmail.com //http://www.tpodt.tk //Thanks to Ghandi for his posts on tuts4you.com. I just combined his info //to a script... //FAQ: //Q: What to do when the script asks me to enter 'the start of junk code'? //A: Search down untill you see the code going from clear disassembly to // crap. Enter the address under the last 'normal' jump. This can't be // done withour user input because you'll need the 'junk marker' for // each specific version of Armadillo (the markers even change in betas // I thought) //Q: What to do when the script asks me if I want the fast or the slow way // for restoring imports? //A: Always use the fast way exept if your target imports the file // "ArmAccess.dll". The slow function is not properly tested! It may fail // on versions 4.xx, 5.xx and 6.xx (I tested this script on Armadillo 8.4) //Q: I dont understand what happens here, HELP! //A: Read tutorials on Armadillo & ODbgScript. Remember: This script only // automates an unpacking procedure. You wont learn unpacking from it!! //Used byte signatures: //#5F5253# = ASCII "_RS" //#75??# = JE SHORT ???????? //#0F84????????# = JE LONG ???????? //#6A00# = PUSH 0 //#6A01# = PUSH 1 //#6800010000# = PUSH 100 //#E8????????# = CALL ???????? //#83C?04# = ADD [register],4 //#33??E9????????# = XOR [register],[register], JMP LONG ???????? //--------------------------------------------------------------------------//

msgyn "YES for CopyMem2, NO for Standard (+ Debug Blocker)" cmp $RESULT, 0 je standardprotection MSGYN "YES for CodePage, NO for imports" CMP $RESULT, 0 JE imports bc //Remove all breakpoins bphwc //Remove all HW breakpoins lclr //Clear the script log //BP Variables: var OpenMutexA var GetEnvironmentVariableA var VirtualProtect var LoadLibraryA var CreateThread //Normal variables: var ImageBase

var var var var var var var var var var var var var var

EnvironmentVariableName junk_finder junk1 junk2 je1 je2 EncryptDecrypt no_iat_elimination iat_elimination method2 addr_jnz code_size end_txt temp

//Get ImageBase: pusha exec push 0 call GetModuleHandleA ende mov ImageBase, eax popa //Set the breakpoint variables: gpa "OpenMutexA", "kernel32.dll" mov OpenMutexA, $RESULT gpa "GetEnvironmentVariableA", "kernel32.dll" mov GetEnvironmentVariableA, $RESULT gpa "VirtualProtect", "kernel32.dll" mov VirtualProtect, $RESULT gpa "LoadLibraryA", "kernel32.dll" mov LoadLibraryA, $RESULT gpa "CreateThread", "kernel32.dll" mov CreateThread, $RESULT //Fool the Debug-Blocker: bp OpenMutexA erun bc estep bp OpenMutexA erun bc rtr mov eax,1 log "Debug-Blocker fooled!" //Skip the famous CopyMem2 crash: loop1: bp GetEnvironmentVariableA erun bc mov EnvironmentVariableName, [esp+4] estep cmp [EnvironmentVariableName], #5F5253# //Compare the variable name with "_RS"

jne loop1 eval "Environment Variable '_RS' Found at 0x{EnvironmentVariableName}!" log $RESULT rtr esti find eip, #0F84????????# //Look for JE LONG cmp 0, $RESULT je error bp $RESULT erun bc xor !ZF, !ZF //Flip the Z-flag if needed log "CopyMem2 Crash fixed!" //Get near the license checking bp OpenMutexA erun bc //To get near import-scrambling bp VirtualProtect erun bc //Get near the "magic jump" bp LoadLibraryA erun bc //Get in the imort-destruction code mov junk_finder, ebp add junk_finder, 4 log junk_finder bp [junk_finder] erun bc //Because we don't know all the markers we ask the user to search... :) ask "Search down for junk code and enter the start address here (use PageDown to scroll):" mov junk1, $RESULT bphws junk1, "x" restored: erun bphwc ask "Search down for junk code again and enter the start address here (use PageD own to scroll):" mov junk2, $RESULT bphws $RESULT, "x" erun bphwc find eip,#33??E9????????# //XOR [register], [register], JMP LONG find $RESULT, #0F84????????# //Look for the 1st JE LONG after that mov je1, $RESULT //Move the result in a variable inc $RESULT //increase the result for next search find $RESULT, #0F84????????# //Look for JE LONG

mov je2, $RESULT //move the result in a variable //run till the 1st JE LONG: bp je1 erun bc mov iat_elimination, !ZF //Get some info about it: gci eip, DESTINATION mov no_iat_elimination, $RESULT xor !ZF, !ZF //Flip flag (for non-IAT Elimination targets) //run till the 2nd JE LONG: bp je2 erun bc xor !ZF, !ZF //Flip z-flag find eip,#6A00# //Look for PUSH 0 find $RESULT, #E8????????# //Look for the 1st call after that mov EncryptDecrypt, $RESULT //Move the result in a variable //Decrypt the Code Page! bp EncryptDecrypt erun bc estep log "Code blocks decrypted" cmp 0, iat_elimination je done1 mov eip, no_iat_elimination jmp done2 error: msg "Error, maybe unsupported version" done1: find eip, #6A01# bphws $RESULT, "x" erun find eip, #E8????????# add $RESULT, 5 mov eip, $RESULT done2: bphwc bphws CreateThread, "x" loop2: erun rtr esti find eip, #5?# cmp $RESULT, eip jne loop2

rtr esti find eip, #FFD?# inc $RESULT find $RESULT, #FFD?# bphws $RESULT, "x" erun esti mov OEP, eip mov OEP_rva, eip sub OEP_rva, ImageBase bphwc bc jmp end_final no_code: erun jmp end_final2 end_final: eval "OEP: {OEP}, ({OEP_rva}). {end_txt} You may also need to the the Access of the code section to 'Full Access' if you want to dump the target..." msg $RESULT log $RESULT, "" JMP end imports: bc //Remove all breakpoins bphwc //Remove all HW breakpoins lclr //Clear the script log //BP Variables: var OpenMutexA var GetEnvironmentVariableA var VirtualProtect var LoadLibraryA var CreateThread //Normal variables: var EnvironmentVariableName var je1 var je2 var var var var method2 addr_jnz end_txt temp

//Get ImageBase: pusha

exec push 0 call GetModuleHandleA ende mov ImageBase, eax popa //Set the breakpoint variables: gpa "OpenMutexA", "kernel32.dll" mov OpenMutexA, $RESULT gpa "GetEnvironmentVariableA", "kernel32.dll" mov GetEnvironmentVariableA, $RESULT gpa "VirtualProtect", "kernel32.dll" mov VirtualProtect, $RESULT gpa "LoadLibraryA", "kernel32.dll" mov LoadLibraryA, $RESULT gpa "CreateThread", "kernel32.dll" mov CreateThread, $RESULT //Fool the Debug-Blocker: bp OpenMutexA erun bc estep bp OpenMutexA erun bc rtr mov eax,1 log "Debug-Blocker fooled!" //Skip the famous CopyMem2 crash: loop1_i: bp GetEnvironmentVariableA erun bc mov EnvironmentVariableName, [esp+4] estep cmp [EnvironmentVariableName], #5F5253# //Compare the variable name with "_RS" jne loop1_i eval "Environment Variable '_RS' Found at 0x{EnvironmentVariableName}!" log $RESULT rtr esti find eip, #0F84????????# //Look for JE LONG cmp 0, $RESULT je error_i bp $RESULT erun bc xor !ZF, !ZF //Flip the Z-flag if needed log "CopyMem2 Crash fixed!" //Get near the license checking bp OpenMutexA

erun bc //To get near import-scrambling bp VirtualProtect erun bc //Get near the "magic jump" bp LoadLibraryA erun bc //Get in the imort-destruction code mov junk_finder, ebp add junk_finder, 4 log junk_finder bp [junk_finder] erun bc msgyn "Click YES for the fast way of restoring imports. Click NO if the target c alls the internal ArmAccess.dll" cmp $RESULT, 1 jne method2_i find eip, #6800010000# //Find PUSH 100 find $RESULT, #E8????????# //Find the 1st call after PUSH 100 gci $RESULT, DESTINATION //Get the destination of the call asm $RESULT, "retn" jmp restored2_i method2_i: find eip, #6800010000# //Look for push 100 find $RESULT, #E8????????# //Look for the 1st call after push 100 find $RESULT, #6800010000# //Look for the 1st PUSH 100 after that find $RESULT, #83C?04# //Look for ADD [register],4 find $RESULT, #75??# //Look for the 1st JNZ SHORT after that mov addr_jnz, $RESULT //Move the result in a variable bphws addr_jnz, "x" //Set a BP on that variable //Flip flags manually because of the CRC check (can take some time) imports_loop_i: erun cmp eip, addr_jnz jne restored2_i mov !ZF, 1 jmp imports_loop_i restored2_i: bc bphwc erun msg "Import table restored!" jmp end standardprotection: dbh bc

bphwc var var var var var var var var var var OpenMutexA CreateMutexA mutex_name GetEnvironmentVariableA VirtualProtect LoadLibraryA CreateThread compare ImageBase junk_finder

pusha exec push 0 call GetModuleHandleA ende mov ImageBase, eax popa gpa "OpenMutexA", "kernel32.dll" mov OpenMutexA, $RESULT gpa "GetEnvironmentVariableA", "kernel32.dll" mov GetEnvironmentVariableA, $RESULT gpa "VirtualProtect", "kernel32.dll" mov VirtualProtect, $RESULT gpa "LoadLibraryA", "kernel32.dll" mov LoadLibraryA, $RESULT gpa "CreateThread", "kernel32.dll" mov CreateThread, $RESULT gpa "CreateMutexA", "kernel32.dll" mov CreateMutexA, $RESULT msgyn "Is the target using Debug-Blocker?" cmp $RESULT, 0 je standard_protection_s bp OpenMutexA erun bc mov mutex_name,[esp+0C] exec pushad pushfd push {mutex_name} push 0 push 0 call CreateMutexA popfd popad ende

//bp OpenMutexA //erun //bc //estep //bp OpenMutexA //erun //bc //rtr //mov eax,1 standard_protection_s: msgyn "Armadillo NAG? (Click No if you are unsure)" cmp $RESULT, 1 je arm_nag_s loop0_s: bp GetEnvironmentVariableA erun bc mov compare, [esp+4] cmp [compare], #5F5253# estep jne loop0_s loop1_s: bp OpenMutexA erun bc mov compare, [esp+C] add compare, 8 cmp [compare], #3A53494D554C41544545585049524544# estep jne loop1_s bp VirtualProtect erun bc jmp no_nag_s arm_nag_s: msg "Click the pause (F12) button if NAG is loaded. Click OK to continue..." erun no_nag_s: bp LoadLibraryA erun bc mov junk_finder, ebp add junk_finder, 4 bphws [junk_finder], "x" erun bphwc msgyn "Click YES for the fast way of restoring imports. Click NO if the target c alls the internal ArmAccess.dll" cmp $RESULT, 1 jne method3_i find eip, #6800010000# //Find push 100

find $RESULT, #E8????????# //Find the 1st call after PUSH 100 gci $RESULT, DESTINATION //Get the destination of the call asm $RESULT, "retn" jmp loop2_s method3_i: bp CreateThread find eip, #6800010000# //Look for push 100 find $RESULT, #E8????????# //Look for the 1st call after push 100 find $RESULT, #6800010000# //Look for the 1st PUSH 100 after that find $RESULT, #83C?04# //Look for ADD [register],4 find $RESULT, #75??# //Look for the 1st JNZ SHORT after that mov addr_jnz, $RESULT //Move the result in a variable bphws addr_jnz, "x" //Set a BP on that variable //Flip flags manually because of the CRC check (can take some time) imports_loop2_i: erun cmp eip, addr_jnz jne loop2_s2 mov !ZF, 1 jmp imports_loop2_i restored3_i: bc bphwc loop2_s: bp CreateThread erun loop2_s2: bc rtr esti find eip, #5?# cmp eip, $RESULT jne loop2_s bc rtr esti find eip, #FFD?# inc $RESULT find $RESULT, #FFD?# bp $RESULT erun bc esti find eip, #60# cmp eip, $RESULT jne done_s msgyn "Do you want me to unpack the detected UPX protection?" cmp $RESULT, 0 je done_s //My UPX Script: find eip, #61#

cmp $RESULT, 0 je fail_s bp $RESULT erun bc $RESULT find eip, #E9????????# cmp $RESULT, 0 jne normal_s find eip, #C3# cmp $RESULT, 0 jne normal_s find eip, #E8????????# cmp $RESULT, 0 jne normal_s jmp fail_s normal_s: bp $RESULT erun bc $RESULT esti jmp done_s fail_s: msg "Fail with unpacking UPX, do this manually..." done_s: mov OEP, eip mov OEP_rva, eip sub OEP_rva, ImageBase bc dbs //Unhide from IsDebuggerPresent eval "OEP: {OEP}, ({OEP_rva}), Imports Fixed: Yes!" msg $RESULT end: LOG "Done!"