You are on page 1of 11

27thSeptember2014

Reversingwithimmunitydebugger

InthispostI'mgoingtoshowyouhowtouseimmunitydebuggertoreverseengineerandcrackaprogram.Ifyou
haven't used immunity debugger or olly debugger before you can check this post [http://sgros
students.blogspot.com/2014/05/immunitydebuggerbasicspart1.html]
and
this
post
[http://sgros
students.blogspot.com/2014/09/immunitydebuggerbasicspart2.html] where I explain some basics of using immunity
debugger.

Crackmes
Acrackmeisaprogramspecificallywritteninpurposeofbeingcracked(itis100%percentlegal).Reverseengineers
use such programs as kind of a practice. The largest community for crackme programs is crackmes.de
[http://crackmes.de/] .CrackmewhichI'mgoingtoanalyzeisRewrit'scrackme10.
Preliminaryanalysis
Soletsloadupourprograminimmunitydebuggerandstartit.Whenprogramisfirstloadeditstopsondefaultentry
pointbreakpoint,justclickRuntogetitrunning.Weseeitasksusforausername.Letsinputtestandhitenter.Okay
nowitasksusforapassword.Inputtestagainandhitenter.Asitcanbeseenwegetamessagewhichsayswe
haveenteredabadpassword.

[http://4.bp.blogspot.com/
W50FPO8KxZ4/VCLmVu4CIjI/AAAAAAAAAJs/FJweDq3vQeQ/s1600/preliminary.PNG]

Analysisofthebinaryfile
Ourfirstobjectiveshallbetofindwhereinbinaryfilepasswordwetypediniscomparedtotherealpassword.We
see that in case when our password is incorrect we get message Bad password. So lets try to find where that
messageisloadedupanddisplayed.TodothatweshallsearchbinaryfileforstringBadpassword,ortobemore
precise, we shall search binary for all strings which are referenced to in the code.This method is effective only if
binaryisn'tpacked,obfuscatedorencryptedinanyway.
To find all referenced text strings in the code right click on the disassembly window, choose Search for > All
referencedtextstrings.

[http://2.bp.blogspot.com/
t008GPZvu3o/VCQOgCIaVSI/AAAAAAAAAJ8/cEAr6aQZGs/s1600/textstrings.png]

WefoundinstructioninwhichstringBadpasswordisreferenced.IfyoulookatlineaboveyoucanseestringGood
job!andinstructioninwhichisreferencediscoupleofinstructionsbeforetheonewherethestringBadpasswordis
referenced. There is a good chance we will find JMP (some variant of it) couple of instructions before these
instructions and that they are in fact part of a ifelse statement. Let's follow any one of the two instructions in
disassemblyandtrytofindouthowtogettheCPUtoexecuteinstructionwithGoodjob!insteadoftheonewithBad
password.DoubleclickonanyofthosetwolinesorrightclickandselectFollowinDissasembler.

[http://4.bp.blogspot.com/EaW49xDAmz8/VCQOgpr9KuI/AAAAAAAAAKA/MjaRcqdV7Rk/s1600/textsrings2.png]

Ifyoulookcoupleofinstructionabovethesetwo,attheaddress00401B6Eyou'llfindJE(jumpequal)instructionand
line above is TEST instruction with AL register (AL register is the one which holds the lowest 8 bits of EAX
register)asanargument.DestinationofJEinstructionisjustbehindthecodethatloadsstringGoodjob!andcalls
some function. So in order to get the Good job! message this instruction must never jump. TEST instruction is
actually logic AND instruction and only way JE instruction is going to jump after TEST instruction which has both
arguments same is if argument is equal to zero. We can deduce that AL register holds boolean value which
determinesifourpasswordisequaltotherealpassword.

[http://3.bp.blogspot.com/N4bfc15R2hQ/VCQmAlF_f4I/AAAAAAAAAKU/5MZaz83B_os/s1600/picture1.png]

Function which is being called before TEST instruction is probably one which is comparing our password with the
realpassword.Let'scheckthat,rightclickonthatCALLinstructionandpressFollow.Let'slookatthecodeofthe
function.

[http://1.bp.blogspot.com/Ji3cM8yDiVg/VCQuoenM3I/AAAAAAAAAKk/LWysQEpiYWs/s1600/code1.PNG]

Firsttwoinstructionsarestandardfunctionprologue,savingoldframepointerandsettingnewone.Then24bytes
(18 hex = 24 decimal) of memory are allocated, enough for 6 variables (under assumption each variable takes 4
bytes). To know what next four instructions are doing you need to understand stack and stack(function) frame
[http://www.csee.umbc.edu/~chang/cs313.s02/stack.shtml] .Inshort,addressesthatarehigherthanEBPareparameters

tothefunction(withthefirstonebeingattheoffset+8)andaddressesthatarelowerthanEBParefunctionslocal
variables.Sothenextfourinstructionsareactuallytransferringthisfunctionsfirsttwoparameterstobeparameters
tothenextcalledfunction.Sometimes(withrightcompilingoptions)compilersaregoingtoreserveplaceinadvance
for function parameters and then load them up with MOVinstructioninsteadofusingPUSH instruction (its faster).
Let'sfirstfocusonthecodeaftertheCALLinstructionandthenwe'llgoandseewhathappensinthecalledfunction.
FirstinstructionsavesvalueofEAXregisterasthefirstlocalvariable.SotheEAXregisterholdsthereturnvaluefrom
thefunction.Thenthatvalueisbeingcomparedwiththezero,andifitisequalALregisterissettothevalueof1
(see
SETE
[http://x86.renejeschke.de/html/file_module_x86_id_288.html]
).
MOVZX
[http://x86.renejeschke.de/html/file_module_x86_id_209.html] instructionfillstherestoftheEAXinstructionwiththezeroes.
Next instruction saves that value in the first local variable and the one after that does nothing practically since its
movingsamevalueintheEAXregister.Sotheactualcomparisonisn'tdoneinthisfunctionbutthebooleanvalue
which we test to determine if we have got the right password is set in this function. It's a good guess that next
function does the actual comparing, and it's also good guess that our two parameters are actually pointers to our
typedinpasswordandtherealpassword.Let'smoveontothenextfunction.

[http://1.bp.blogspot.com/sNjxY_DufU8/VCQ9R3QWgSI/AAAAAAAAAK0/oVmxUIAMZ1k/s1600/code2.PNG]

Againwehaveourstandardfunctionprologueandthenallocating32bytesofspace.Nextinstructionissavingvalue
ofEBXregisteronthestack(againsubstitutionforPUSH),thenfirstparameterisloadedintoEAXandthenESIand
EDIregistersaresavedonthestack.Oursuspicionthatargumentsarepointers(atleastfirstone)isconfirmedin
thenextinstruction.ValuewhichislocatedattheaddresspointedtobyfirstargumentisloadedintoEAX.Thatvalue
isthensavedasthe8thlocalvariable.Nextinstructionloadsthevaluelocated12bytesbehindcurrentvalue,that
tells us we'r probably dealing with some kind of the data structure. Then second argument is loaded and its first
member is saved in EDX register. Address of the fifth local variable is saved in the EAX and second member of

second data (its actually the fourth since it is 12 bytes after the first one but because those 2 in the middle aren't
used I'm going to refer to it as the second) structure is saved in the EBX.In the next 4 instructions values of the
secondmembersofdatastructuresarecomparedandifnecessaryEAXisadjustedtobepointertothememberof
thefirstdatastructure(ifthememberofthefirstdatastructureislesserthanmemberoftheseconddatastructure).
NotethatJBinstructionisonethatchecksthestatusoftheunsignedvalues,sothattellsusthatsecondmembersof
the data structure are unsigned values. We will ignore CLD instruction for a moment. In the next 3 instructions
registersEDIandESIareloadedwithourfirstmembersofdatastructuresandinECXregisterisputlesserfromthe
two
unsigned
values.
REPE
[http://x86.renejeschke.de/html/file_module_x86_id_279.html]
CMPS
[http://x86.renejeschke.de/html/file_module_x86_id_38.html] instruction compares bytes pointed to by EDI and ESI
registersaslongastheyareequal.Thatisastringinstructionsothereisagoodprobabilitywefoundplacewhere
our password is compared to the real one. CLD [http://x86.renejeschke.de/html/file_module_x86_id_29.html] instruction
whichweignoredbeforeisusedtodeterminewhetherEDIandESIregistersareincrementedordecremented.Since
ECXholdsthevaluewhichdetermineshowmanytimesREPEinstructionisgoingtorun(untilECXiszero,itisone
ofthe2conditions,otheronebeingbytesatthelocationsareequal)wecanassumethattheECXholdsthenumber
of characters of the string which is shorter, meaning second member of the data structure is number of the
characters. In the rest of the function register EAX is set to hold the return value (0 if the strings are equal) and
startingvaluesarereturnedtotheirregisters.
Now to verify if our static analysis was correct and to get the better understanding of functions go back to the
address 00401B67, put breakpoint on that instruction and step through these 2 functions. Let's stop on address
00412C8EandlookattheregistersECX,EDIandESItoseeifourguessaboutvaluesintheseregisterswascorrect
(althoughyoucanseethatbeforethisinstruction).AswecanseeECXregisterholdsvalue4,whichislengthofour
typedinpassword.ESIregisterholdstheaddressofourtypedinpassword"test",andEDXregisterholdsthevalue
ofthestring"dQhdhhbhb"whichisprobablytherealpassword.

[http://3.bp.blogspot.com/BbKbQXnytMU/VCUw1aJINBI/AAAAAAAAALE/Dmk2eaJOCuw/s1600/code3.png]

Now try restarting the program and for username input test and for password dQhdhhbhb. We have got the
messageGoodjob!. We were successful in discovering the password. But restart the program and for username
typetest1andforthepassworddQhdhhbhb.OnceagainwehavegotthemessageBadpassword.It'sobviousthat
passwordisgeneratedfromusernamesomehowanditwouldbegoodtodiscoverhowitisbeinggenerated.Butfor
now let's try something else, let's see if we can change some part of the code so that our "good"message would
alwaysbedisplayed.Goodplacetodosomethinglikethatwouldbepartofthecodewhereitisdecidedwhichstring
isgoingtobeloadedupanddisplayed.

Patching
Gobacktoaddress00401B6E,whereitisdecidedwhichmessageisgoingtobedisplayed.Wewanttoneverjump
onthisinstruction,butrathertocontinuedowntothegoodmessage.Thiscanbeachievedbymultipleways.Oneof
those is simply to change JEinstruction to NOP (no operation). To do that double click on JE instruction, you are
goingtogetwindowlikethis:

[http://2.bp.blogspot.com/
XxO9qFTSJVw/VCVHSP2otdI/AAAAAAAAALU/cGUibEHqPYc/s1600/patch1.PNG]

NowwriteNOPinsteadofthatJEinstruction.

[http://3.bp.blogspot.com/gWQfN
bFwjk/VCVHSez2LmI/AAAAAAAAALY/mez87V5N6To/s1600/patch2.PNG]

ClickAssembleandCancel.IfyoudontclickCanceldebuggerisgoingtocontinurereplacinginstructionswithNOP.
YoucanseenowthatwehavetwoNOP'sinsteadofJEinstruction.ThereasontherearetwoNOP'sisthatNOPis1
byteinstructionandJEis2byteinstruction,so2NOPinstructionsarerequiredtoreplaceoneJEinstruction.

[http://1.bp.blogspot.com/X541ShNoyOg/VCVHSdl2dqI/AAAAAAAAALk/DvnsBBVNHpc/s1600/patch3.PNG]

Nowrestartprogramagainandtypetestforbothusernameandpassword,withourchangesweshouldgetGood
job!message.Asyoucansee,wehavesuccessfullycrackedprogramanditdisplayswantedmessagenow,even
thoughwehaveenteredthewrongpassword.

[http://4.bp.blogspot.com/
CrepPHzjgr0/VCVQ0Q0NK8I/AAAAAAAAAL0/WhikZEZydpQ/s1600/success.PNG]

Savingthepatch

Theonlythingleftforustodoistosavethepatch.Patchesarenotautomaticallysavedandifyoucloseandopen
yourprogramorrestartit,patchwillbegone.YoucanseeallofyourpatchesinPatchwindow(underView tab or
pressCTRL+P).

[http://1.bp.blogspot.com/Ln2jbzWXutE/VCVUquRFrnI/AAAAAAAAAMA/iG3_ZUqjG9o/s1600/patch4.png]

TosavethemadechangesrightclickanywhereinthedisassemblywindowsandchooseCopytoexecutable>All
modifications.

[http://3.bp.blogspot.com/
mZXkpYwN_K0/VCVXXhVjcWI/AAAAAAAAAMM/UlXN1ROrVc/s1600/saving.png]

It will ask you if you want to save all changes, press Copyall. If you want to copy only selection of the binary file,
highlightthepartyouwanttocopyandinsteadofAllmodificationschooseSelection.

[http://2.bp.blogspot.com/
iKVc5hxxiBE/VCVYh7CR54I/AAAAAAAAAMY/E6WgDI94B1M/s1600/saving2.PNG]

Afterthatanewwindowsisgoingtoopenwhichisahexdumpofourexecutablebutwithourpatchinside.Butnew
executable is still not saved on the disk, this image is in the working memory. To save it on the disk right click
anywhereinthisnewwindowanselectSavefile.Typeindesiredusernameandlocationanditissavedforgood.I
have named my copy Cracked. Let's open it, so that we can be certain that our patching has succeeded. For
usernameandpasswordtypetest1andlet'slookattheresult.

[http://3.bp.blogspot.com/
X_a_IPGkAas/VCVp5enI3iI/AAAAAAAAAMo/vdKNC_ZzkdA/s1600/success1.PNG]

Asyoucanseeithassucceeded.Inthispostwesawhowtoanalyzebinaryfiletofindinformationwewantandhow
to apply patch. In next post we are going to delve deeper in analysis and try to locate place in the code where
passwordisgeneratedandwewillmakeourownkeygenerator.
Posted27thSeptember2014byIgorNovkovi
Labels:assembly,cracking,english,immunitydebugger,inovkovic,reverseengineering
0 Addacomment

Enteryourcomment...

Commentas:

Publish

Selectprofile...

Preview