Flare-On 7 — 06 Codeit
Getting started
In the sixth challenge we are given with a simple file named codeit.exe
. As in most of the challenges, let’s start by executing the file
command on it.
$ file codeit.exe
codeit.exe: PE32 executable (GUI) Intel 80386, for MS Windows, UPX compressed
Similar to the 2nd challenge, codeit.exe
is compressed with UPX
. Using the upx
utility, we can decompress it.
$ upx -d decompressed_codeit.exe -o decompressed_codeit.exe
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2020
UPX git-d7ba31+ Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020
File size Ratio Format Name
-------------------- ------ ----------- -----------
963584 <- 481280 49.95% win32/pe decompressed_codeit.exe
Unpacked 1 file.
Running file
on the decompressed file doesn’t give us meaningful results:
$ file decompressed_codeit.exe
decompressed_codeit.exe: PE32 executable (GUI) Intel 80386, for MS Windows
If file
doesn’t provide useful information, we can try our luck with Detect It Easy, a “program for determining types of files for Windows, Linux and MacOS.”
$ diec decompressed_codeit.exe
PE: library: AutoIt(-)[-]
PE: compiler: Microsoft Visual C/C++(2013)[-]
PE: linker: Microsoft Linker(12.0*)[EXE32]
Detect It Easy recognized this file as an Auto It executable. And this explains the name of the challenge — “codeit”. Let’s run it in a VM and see what happen.
The program asks for our input, processing it, and generate QR code. Let’s now extract the AutoIt code from inside the binary. Windows users can use the famous Exe2aut that should easily do the trick. We used Autoit-Ripper as it is easier to run on Linux command line.
$ python AutoIt-Ripper/main.py codeit.exe > script.au3
Oh boi, what a mess. Opening the file we saw a huge mess. Hundreds of obfuscated Auto It lines of code.
Cleaning up the code
We highly recommend to take the time during a challenge and clean the code you have. Working on a clean code will make your work much easier and less frustrating. So let’s clean it up a bit.
$ wine Tidy.exe script.au3
Tidying up the script indeed sparked joy in us, but not enough. Briefly going over it we still noticed a painful string obfuscation. Scrolling to the bottom, we can see a messy function that looks like this:
FUNC AREIHNVAPWN()
LOCAL $DLIT = "7374727563743b75696e7420626653697a653b75696e7420626652657365727665643b75696e742062664f6666426974733b"
$DLIT &= "75696e7420626953697a653b696e7420626957696474683b696e742062694865696768743b7573686f7274206269506c616e"
$DLIT &= "65733b7573686f7274206269426974436f756e743b75696e74206269436f6d7072657373696f6e3b75696e7420626953697a"
$DLIT &= "65496d6167653b696e742062695850656c735065724d657465723b696e742062695950656c735065724d657465723b75696e"
...
... [Truncated for readability]
...
GLOBAL $OS = STRINGSPLIT($DLIT, "4FD5$", 261)
ENDFUNC
It seems like the function creates a huge string of hex values into the $DLIT
variable, and then split it by the delimiter 4FD5$
into a list in the global variable $OS
. Looking around, it seems like the $OS
variable is used more than 330 times in the program, always as an argument to the AREHDIDXRGK
. This function is very simple as all it does is converting the hexadecimal values to a string.
FUNC AREHDIDXRGK($FLQLNXGXBP)
LOCAL $FLQLNXGXBP_
FOR $FLRCTQRYUB = 261 TO STRINGLEN($FLQLNXGXBP) STEP 517
$FLQLNXGXBP_ &= CHR( DEC( STRINGMID($FLQLNXGXBP, $FLRCTQRYUB, 517)))
NEXT
RETURN $FLQLNXGXBP_
ENDFUNC
If we will look around we can see that when the program is trying to access the $OS
variable, it doesn’t specify a numeric index, but other variables that equal the desired numeric value. For example, $OS[$FLBZBCWQXO]
will access $OS
in index 11 since $FLBZBCWQXO
equals 11.
As cleaning us this mess will help us a lot, let’s do it.
from malduck import unhex
consts = {"FLAVEKOLCA": 0, "FLERQQJBMH": 1, "FLOWFRCKMW": 0, "FLMXUGFNDE": 0, "FLVJXCQXYN": 2, "FLDDXNMRKH": 0, "FLROSEEFLV": 1, "FLPGRGLPZM": 0, "FLVZRKQWYG": 0, "FLYVORMNQR": 0, "FLVTHBRBXY": 1, "FLXTTXKIKW": 0, "FLGJMYCRVW": 1, "FLCEUJXGSE": 0, "FLHPTOIJIN": 0, "FLRZPLGFOE": 0, "FLIBOUPIAL": 0, "FLIDAVTPZC": 1, "FLOEYSMNKQ": 1, "FLAIBUHICD": 0, "FLEKMAPULU": 1,"FLWECMDDTC": 1, "FLWJXFOFKR": 0, "FLHAOMBUAL": 0, "FLDTVRLADH": 1, "FLPQIGITFK": 1, "FLBXTTSONG": 1, "FLJLRQNHFC": 0, "FLEMDCRQDD": 6, "FLMMAMRWAB": 3, "FLDWUCZENF": 1, "FLRDASKYVD": 0, "FLBAFSLFJS": 6, "FLNDZDXAVP": 4, "FLFGIFSIER": 1, "FLFBQJBPGO": 1, "FLSGVSFCZM": 0, "FLMZRDGBLC": 0, "FLCPXDPYKX": 0, "FLBDDRZAVR": 3, "FLKPXIPGAL": 0, "FLSXHSGAXU": 0, "FLQFPQBVOK": 0, "FLRUBFCAXM": 0, "FLQCKTZAYY": 2, "FLIWGRESSO": 0,"FLYWPBZMRY": 0, "FLQGMNIKMI": 1, "FLGMSYADMQ": 2, "FLOCBWFDKU": 1, "FLGXBOWJRA": 2, "FLMJQNAZNU": 1, "FLSGWHTZRV": 0, "FLFVHRTDDD": 0, "FLRRPWPZRD": 3, "FLRTXUUBNA": 1, "FLJGTGZRSY": 1, "FLSGRRBIGG": 1, "FLJKEOPGVH": 1, "FLSVFPDMAY": 0, "FLQWZPYGDE": 0, "FLVJQTFSIZ": 1, "FLYPDTDDXZ": 0, "FLCXAAENIY": 1, "FLXAUSHZSO": 1, "FLXXQLGCJV": 1, "FLAVACYQKU": 0, "FLVIYSZTBD": 7, "FLPDFBGOHX": 0, "FLFEGERISY": 7, "FLILKNHWYK": 0,"FLOQYCCBVG": 2, "FLXIGQOIZB": 4, "FLZWIYYJRB": 3, "FLYXHSYMCX": 0, "FLTJKUQXWV": 0, "FLALOCOQPW": 0, "FLKLIVKOUJ": 4, "FLADCAKZNH": 2, "FLBKJLBAYH": 1, "FLBXSAZYED": 0, "FLNBEJXPIV": 1, "FLMDZXMOJV": 1, "FLWDJHXTQT": 0, "FLRQJWNKKM": 0, "FLODKKWFSG": 2, "FLEBLUTCJV": 6, "FLUSBTJHCM": 3, "FLWWNBWDIB": 1, "FLHHAMNTZX": 0, "FLALLGUGXB": 1, "FLEVBYBFKL": 5, "FLNMJXDKFM": 1, "FLFKEWOYEM": 1, "FLJMVKKUKJ": 1, "FLULKQSFDA": 0,"FLBGUYBFJG": 3, "FLVKHMEVKL": 2, "FLSKOEIXPO": 1, "FLTYGFAAZW": 0, "FLJSMLMNMB": 2, "FLISPMMIFY": 1, "FLLCQILIYN": 0, "FLCKPFJMVI": 1, "FLRSLVNJMF": 3, "FLNHHTFKNM": 1, "FLAYRXAWKI": 0, "FLDQFFSIWV": 0, "FLVFWRJMJD": 0, "FLCVMQVLNH": 0, "FLXXXSTNEV": 1, "FLKHSHKRUG": 0, "FLPOMTLEUC": 0, "FLNZCHDMSU": 2, "FLJZHXWIBZ": 0, "FLLUWMJHEX": 0, "FLXIFITLBZ": 2, "FLFXAWZKTB": 0, "FLNCKSFUSQ": 0, "FLSZXBCAXW": 0, "FLEWLXBTZE": 2,"FLFFKMNRIN": 5, "FLNXTETUVO": 6, "FLVUVSUZBC": 0, "FLZPWBDCWM": 0, "FLFVGBQFSF": 2, "FLQZHVGEIV": 0, "FLKBPMEWRR": 0, "FLWJUGKIIW": 2, "FLOICBRQFW": 0, "FLCXRPCJHW": 1, "FLMAYHQWZL": 0, "FLJTCWUIDX": 4, "FLGWUBUCWO": 3, "FLLAWKNMKO": 0, "FLHUZJZTMA": 0, "FLMEOBQOPQ": 4, "FLIYCUNPDR": 1, "FLVEGLZONS": 3, "FLHSGHSQKV": 1, "FLTPQPQKPF": 1, "FLQAJQCGNB": 1, "FLANJWGYBT": 6, "FLDZQRBLUG": 4, "FLHDPHDQOB": 2, "FLQOPLETEO": 4,"FLMYTLHXPO": 2, "FLPEVDRDLO": 0, "FLPTDINDAI": 0, "FLGUJVUKWS": 2, "FLKAWUUSHA": 0, "FLJUOLPKFQ": 0, "FLCNPJSXCG": 0, "FLMHZUMMPO": 2, "FLHRJKQVRU": 2, "FLOBWIUVKW": 4, "FLMVBXJFAH": 3, "FLQOCSRBGG": 0, "FLPOCAGRLI": 0, "FLWFNELJWG": 0, "FLEVPVMAVP": 4, "FLFSJHEGVQ": 3, "FLONFGETWP": 4, "FLCXGMXXSZ": 5, "FLICPDEWWO": 6, "FLFAIJOGTB": 1, "FLFAJFOKZY": 0, "FLQYKIUXHO": 0, "FLPCRFTWVR": 0, "FLVJDLWVHM": 0, "FLQHEPDEKS": 1,"FLRUJSTIKI": 1, "FLAEFECIEH": 1, "FLAIEIGMMA": 1, "FLKVNTCQFV": 6, "FLMKMLLSNU": 0, "FLEFSCAWIJ": 1, "FLXEQKUKPP": 2, "FLSNJMVBTP": 1, "FLFWYDELAN": 1, "FLZOYCEKPN": 1, "FLXXGKPIVV": 1, "FLTZJPMVXN": 1, "FLFTJYBGVR": 7, "FLZTYFGLTV": 1, "FLFLAVKZAQ": 1, "FLMJFBNYEC": 1, "FLBIGTHXYK": 3, "FLJIJXQYZY": 1, "FLGDNNQSTI": 0, "FLMBJRTHGV": 0, "FLYRTVAUEA": 0, "FLDCGTNAKV": 0, "FLPIFPMBZI": 1, "FLCHQQRKLE": 0, "FLOEZYGQXE": 0,"FLNYFQUHRM": 0, "FLHSOYZUND": 0, "FLCPGMNCTU": 1, "FLPKESJRHX": 0, "FLSXZTEHYJ": 6, "FLNMNJAXTR": 3, "FLGTNLJOVC": 0, "FLQFRONEDA": 7, "FLQZELDYNI": 0, "FLXZYFAHHE": 1, "FLRFDVCKRF": 1, "FLRDWAKHLA": 1, "FLLAZEDTZJ": 1, "FLDBJQQAIY": 2, "FLQHSOFLSJ": 1, "FLOPDVHJLE": 0, "FLPVXADMHH": 0, "FLDCYEGHLF": 2, "FLPXLALOSG": 1, "FLDHTHSNWJ": 1, "FLWTSVPQCX": 1, "FLRRBXOGGL": 1, "FLTGQYKODM": 1, "FLTMXODMFL": 1, "FLVUJARIHO": 1,"FLLDOOQTBW": 3, "FLEHOGCPWQ": 0, "FLMBBMUICF": 0, "FLSFWHKPHP": 4, "FLKKMDMFVJ": 0, "FLMVWPFAPG": 5, "FLFWGVTXRP": 0, "FLIWYJFDAK": 6, "FLTYPFARSJ": 0, "FLTSJLAGJO": 7, "FLWGMWWERS": 0, "FLVAXMAXNA": 8, "FLRJMGOOQL": 1, "FLUOQIYNKC": 0, "FLSFKRALZH": 9, "FLGAVMTUME": 0, "FLYAXYILNQ": 0, "FLHRJRMIIS": 0, "FLZWRIUQZW": 0, "FLVRHZZKVB": 0, "FLYDCWQGIX": 0, "FLYMQGHASV": 0, "FLSWVVHBRZ": 0, "FLYRZXTSGB": 0, "FLAFMMIIWN": 0,"FLGCAVCJKB": 36, "FLIZRNCRJW": 39, "FLHBZVWDBM": 28, "FLBFVIWGHV": 25, "FLOCBJOSFL": 26, "FLIJVRFUKW": 156, "FLOUFWDICH": 28, "FLFAWMKPYI": 25, "FLXSCKORHT": 26, "FLVEGSAWER": 157, "FLSVRBYNNI": 138, "FLTFNAZYNW": 154, "FLTXCJFDTJ": 25, "FLKGPMTRVA": 36, "FLGDEDQZLQ": 158, "FLGSDEIKSW": 28, "FLZGOPKMYS": 39, "FLMTLCYLQK": 2, "FLEGVIIKKN": 0, "FLMHUQJXLM": 1, "FLMSSJMYYW": 0, "FLXNXNKTHD": 2, "FLHZXPIHKN": 3, "FLWIOQNUAV": 4, "FLMIVDQGRI": 0,"FLWFCIOVPD": 150, "FLBRBERYHA": 128, "FLQXFKFBOD": 28, "FLLKGHUYOO": 25, "FLVOITVVCQ": 150, "FLTWXZCOJL": 151, "FLABFAKVAP": 28, "FLDWMPGTSJ": 152, "FLNCSALWDM": 28, "FLXJEXJHWM": 150, "FLMMQOCQPD": 150, "FLCUYAGGUD": 25, "FLXKQPKZXQ": 28, "FLLFTZDHOA": 153, "FLIQYVCBYG": 28, "FLEUHCHVKD": 28, "FLEYXMOFXU": 150, "FLORZKPCIQ": 28, "FLHIQHCYIO": 28, "FLMMQJHZIV": 154, "FLPDPBBQIG": 25, "FLYUGCZHJH": 26, "FLIIEMMOAO": 155, "FLQBXXVJKP": 28, "FLLCWTUUXW": 39,"FLYHHITBME": 19778, "FLEJPKMHDL": 148, "FLKHEGSVEL": 25, "FLXSDMVBLR": 28, "FLIKWKUQFW": 149, "FLHWRPEQLU": 138, "FLGEUSYOUV": 22, "FLUSCNDCWL": 150, "FLOZJUVCPW": 2147483648, "FLHEIFSDLR": 150, "FLMKWZHGSX": 28, "FLKVVASYNK": 150, "FLLNVDSUZT": 150, "FLGZYEDELI": 128, "FLQPLZAWIR": 28, "FLQWWEUBDM": 25, "FLFXFGYXLS": 28, "FLTWCTUNJP": 149, "FLOJQSRRSP": 138, "FLJFQERNUT": 22, "FLNZFZYDOI": 150, "FLEIYNADIW": 1073741824, "FLOMPXSYZT": 150, "FLEUJCYFDA": 28, "FLSUNMUBJT": 150,"FLNEPNLRBE": 26, "FLEWCKIBQF": 135, "FLFBHDCWRZ": 136, "FLVJHZDFOX": 137, "FLZAQHEXFT": 39, "FLCGKJFDHA": 138, "FLPZZBELGA": 1024, "FLSVRWFRHG": 136, "FLOEHUBDBQ": 139, "FLQALTYPJS": 39, "FLYXAWTEUM": 39, "FLZHYDQKFA": 25, "FLXJNUMURX": 30, "FLKKJSWQSG": 21, "FLBWRJDMCI": 11, "FLKAIIDXZU": 140, "FLGHBWHIIJ": 141, "FLAWUYTXZY": 142, "FLKUOYKDCT": 143, "FLQJZIJEKX": 144, "FLDBKUMRCH": 145, "FLVMXYZXJH": 146, "FLWWJKDACG": 4096, "FLSCEVEPOR": 134, "FLOCQAIWZD": 147,"FLPUWWMBAO": 26, "FLOUVIBZYW": 126, "FLMRUDHNHP": 28, "FLHHPBRJKE": 34, "FLRKPARHZH": 26, "FLNYCPUELN": 125, "FLNEGILMWQ": 28, "FLYQWVFHLW": 36, "FLQJTXMAFD": 128, "FLZLVSKJAW": 25, "FLRXMFFBJL": 26, "FLVLZPMUFO": 129, "FLDCVSITMJ": 39, "FLKTWRJOHV": 130, "FLKFRJYXWM": 300, "FLPXFIYLOD": 131, "FLDUSYWYUR": 30, "FLBAHBNTYI": 300, "FLCHKRZXFI": 132, "FLPYQYMBHQ": 55, "FLNPWTOJRC": 300, "FLCTSWLUWO": 300, "FLJRLGNYXN": 133, "FLGOLEIFXH": 134, "FLQPCTTRLM": 13,"FLDCDYLYWL": 34, "FLLVMMTGOD": 26, "FLHVCBZFRN": 37, "FLTRNGARJY": 28, "FLKXLEYZXR": 36, "FLZUFQKSVP": 32771, "FLBJFBSNIP": 36, "FLSWNJCEVA": 36, "FLJHOXSPCA": 28, "FLDENSETKM": 34, "FLIXVXWCRI": 26, "FLMJFDJLZQ": 38, "FLSMZHOBCO": 28, "FLGCKWHRUK": 39, "FLVQLGYUFZ": 36, "FLSHMKXXUH": 36, "FLCUWKMZYT": 34, "FLYCIBMGPD": 26, "FLITCABDOW": 40, "FLICLFTINE": 28, "FLINELZZND": 36, "FLEQCZUVLG": 28, "FLOKXREDDK": 28, "FLYWDVOWNK": 36, "FLYABZRRMV": 34,"FLHMEJJPGG": 26, "FLVTVYIYZU": 125, "FLVVRRDEVF": 28, "FLSVNUQOCX": 36, "FLNPZLYJMK": 34, "FLVCSIGZXL": 26, "FLPUOWUCOH": 126, "FLICCBNVUN": 28, "FLOAIPMNKP": 34, "FLMLUPDWYW": 26, "FLRYNETWBG": 125, "FLPYTXGNAE": 28, "FLYXGOANKM": 36, "FLGIYBXVQU": 127, "FLRIUJDHWU": 16, "FLIDKFVOER": 34, "FLJHXPDLGL": 26, "FLFQEXPZZC": 35, "FLKFNSTOMI": 28, "FLIOPLUJRX": 28, "FLQONPHKJT": 28, "FLWCDNZYBE": 36, "FLXOWOSCQI": 24, "FLOFOSBFLO": 36, "FLKVWONHMY": 4026531840,"FLBKXRNXPV": 28, "FLMGLDSPDJ": 28, "FLTGDGUJKN": 36, "FLTZQIGGDK": 36, "FLNYYTFKEI": 36, "FLZNXMAQLQ": 28, "FLRMMEPZNF": 34, "FLKCTWJXSV": 26, "FLXZNYHVMB": 121, "FLZKHKNUXV": 28, "FLFHWPDVDV": 36, "FLHAAJVXMT": 36, "FLHUKOVWKY": 36, "FLGUYLAQHB": 28, "FLTZVUGNMN": 28, "FLFNYYIXLR": 122, "FLGSADHEXO": 123, "FLBQTUHKMY": 10, "FLCVBSKLVZ": 14, "FLJICUDGOV": 18, "FLJMHYPFZY": 34, "FLCSCARTXG": 26, "FLATLAXFUN": 124, "FLKYEHPFCL": 28, "FLSBVDGRPI": 34,"FLXZAVWMTK": 108, "FLMIGINEJB": 109, "FLTCCTSISO": 110, "FLVOLUBNXK": 111, "FLXVCCPZHB": 112, "FLBYZXYFQO": 113, "FLOPHSMBEK": 114, "FLDPASTQQH": 115, "FLVMFPTZCS": 116, "FLXIREQGPL": 117, "FLHFDXUUDY": 118, "FLFMFYAHHR": 119, "FLLSBIDDPB": 34, "FLUOPLTSMA": 26, "FLBNLSTAUG": 35, "FLYWHXDMQV": 28, "FLGFNZSVNJ": 28, "FLBUCRJUWO": 28, "FLYAFXNZCB": 36, "FLDJWJTTJZ": 24, "FLXPZBCWES": 36, "FLKJEQHLAQ": 4026531840, "FLVEIODZPL": 34, "FLRONCRWTG": 26, "FLMYMAYTOR": 120,"FLWVICVSMS": 83, "FLCPBNDHBQ": 84, "FLIECJFRPE": 85, "FLGHXSBHMP": 86, "FLOAIDMLPX": 87, "FLLVMNCNNY": 88, "FLSFUTYMLY": 89, "FLUHBELZBI": 90, "FLMNJWEHOD": 91, "FLIMUXORRR": 92, "FLWLKKNRPP": 93, "FLHBLIPJBM": 94, "FLUBWWKEML": 95, "FLJUFRNTHN": 96, "FLKTYBYFDH": 97, "FLCRIZOIGP": 98, "FLDRUTGTAI": 99, "FLJWNWABEN": 100, "FLXDASFSUP": 101, "FLVTSKLNDS": 102, "FLGMZABUWZ": 103, "FLWRPPUXSB": 104, "FLMNMTPCBT": 105, "FLTGXUVXHT": 106, "FLTKWHZFIO": 107,"FLYATAFXXS": 58, "FLSWKVICQG": 59, "FLEVOKNZHS": 60, "FLEZSVLBBU": 61, "FLVTQEDRNC": 62, "FLUSNUQYRH": 63, "FLRYYDWMEB": 64, "FLPXKDTIUB": 65, "FLMFELFGBM": 66, "FLAQVPXEFD": 67, "FLCTNOOLTZ": 68, "FLGDVXHTZC": 69, "FLWEHNUNFJ": 70, "FLLONNYIBC": 71, "FLLZJOOGNG": 72, "FLODUOBSCM": 73, "FLGTVYIWTA": 74, "FLEVLQHFZO": 75, "FLOODYSBVZ": 76, "FLZLUAHBYV": 77, "FLVNFPQXZE": 78, "FLAIQGJNTX": 79, "FLCWLFFKHM": 80, "FLQCQUFHQV": 81, "FLRBUZYVZF": 82,"FLHQANOFAV": 26, "FLZJXICUPP": 40, "FLXDFSPFKO": 28, "FLSERMHIOP": 36, "FLCNXXWSYV": 28, "FLDBGPHUMX": 28, "FLXUBNSTGS": 36, "FLETEWAZKH": 41, "FLABBIHPAW": 42, "FLBYMTWVBX": 43, "FLGCIJTDLM": 44, "FLJJIOOIFN": 45, "FLXFEFTBWV": 46, "FLTICITOYZ": 41, "FLMSTPWBRQ": 47, "FLECUYNWDB": 48, "FLJICVVBXQ": 49, "FLTONZTZLF": 50, "FLSBPKAVSY": 51, "FLXPWIFGKD": 52, "FLWXYLVBJS": 53, "FLGCKMZAYX": 54, "FLTWUWURSS": 55, "FLJLIJHEGU": 56, "FLWSWTVQUF": 57,"FLXQUVZRLY": 35, "FLSHMEMJJJ": 28, "FLHQJGLFWS": 28, "FLWVZHFFSC": 28, "FLFRTKCTQE": 36, "FLFAXZHHEN": 24, "FLJHSDAEAV": 36, "FLVWFAVFWC": 4026531840, "FLVORETNCD": 34, "FLYXDICUDB": 26, "FLCRGSIVOD": 37, "FLANAOCMRR": 28, "FLVZOMLPCY": 36, "FLEQWGEGSH": 32780, "FLNPONCVDB": 36, "FLKGSKCVUW": 36, "FLFMPBDWEJ": 28, "FLFWMYXVVJ": 34, "FLJCJBFHKV": 26, "FLGGFVEWXL": 38, "FLNXZDBEHD": 28, "FLUKTGCIEQ": 39, "FLLUEUBEHX": 36, "FLLRDEXKDN": 36, "FLGRKCXAVD": 34,"FLHANAXDHN": 22, "FLAEXDQSRH": 24, "FLGNDUVHBH": 1024, "FLSNPEWUTK": 25, "FLAMFDDUXI": 26, "FLCWFYXDTF": 27, "FLAFBZXAHU": 28, "FLSKISKQTI": 28, "FLFBEVULDL": 29, "FLWNRVOJHL": 300, "FLLLVVITVL": 375, "FLMYERYLNY": 14, "FLAEVYFMEA": 54, "FLOYEOXJVB": 30, "FLUODJMWGW": 31, "FLTIBTJHTT": 32, "FLJOKRIJNY": 54, "FLJEVDJXAE": 31, "FLAUQLVKXG": 20, "FLXZRPAVSW": 30, "FLMDIFZIOP": 31, "FLDFPZZAFD": 33, "FLAVWISYRL": 32, "FLJDTVSDSO": 34, "FLEXJEVBCO": 26,"FLWYBTLYIV": 54, "FLHMBUOOWK": 40, "FLFBIPQYUE": 24, "FLSOPRHUEG": 10, "FLBZBCWQXO": 11, "FLMMEXIVFS": 12, "FLZZZDHSZN": 13, "FLFSOHVCFJ": 14, "FLFSTFCRLF": 15, "FLHXYJQRTQ": 16, "FLUYICWQBF": 17, "FLHDLFYQRT": 18, "FLBRXFHGJG": 19, "FLXUPDTBKY": 20, "FLTNEMQXVO": 97, "FLYGCAYIIQ": 122, "FLBRZNFBKE": 15, "FLCGKRAHML": 20, "FLBMAIUFHI": 10, "FLTMGSDYFV": 15, "FLRAMJDYFU": 21, "FLUKNDIWEX": 22, "FLKPNPAFTG": 25, "FLXEZGJWBW": 30, "FLSGBZULNF": 23,}
str_blub = "7374727563743b75696e7420626653697a653b75696e7420626652657365727665643b75696e742062664f6666426974733b75696e7420626953697a653b696e7420626957696474683b696e742062694865696768743b7573686f7274206269506c616e65733b7573686f7274206269426974436f756e743b75696e74206269436f6d7072657373696f6e3b75696e7420626953697a65496d6167653b696e742062695850656c735065724d657465723b696e742062695950656c735065724d657465723b75696e74206269436c72557365643b75696e74206269436c72496d706f7274616e743b656e647374727563743b4FD5$626653697a654FD5$626652657365727665644FD5$62664f6666426974734FD5$626953697a654FD5$626957696474684FD5$62694865696768744FD5$6269506c616e65734FD5$6269426974436f756e744FD5$6269436f6d7072657373696f6e4FD5$626953697a65496d6167654FD5$62695850656c735065724d657465724FD5$62695950656c735065724d657465724FD5$6269436c72557365644FD5$6269436c72496d706f7274616e744FD5$7374727563743b4FD5$627974655b4FD5$5d3b4FD5$656e647374727563744FD5$4FD5$2e626d704FD5$5c4FD5$2e646c6c4FD5$7374727563743b64776f72643b636861725b313032345d3b656e647374727563744FD5$6b65726e656c33322e646c6c4FD5$696e744FD5$476574436f6d70757465724e616d65414FD5$7074724FD5$436f6465497420506c7573214FD5$7374727563743b627974655b4FD5$5d3b656e647374727563744FD5$7374727563743b627974655b35345d3b627974655b4FD5$7374727563743b7074723b7074723b64776f72643b627974655b33325d3b656e647374727563744FD5$61647661706933322e646c6c4FD5$437279707441637175697265436f6e74657874414FD5$64776f72644FD5$4372797074437265617465486173684FD5$437279707448617368446174614FD5$7374727563742a4FD5$437279707447657448617368506172616d4FD5$30784FD5$30383032304FD5$30303031304FD5$36363030304FD5$30323030304FD5$303030304FD5$43443442334FD5$32433635304FD5$43463231424FD5$44413138344FD5$44383931334FD5$45364639324FD5$30413337414FD5$34463339364FD5$33373336434FD5$30343243344FD5$35394541304FD5$37423739454FD5$41343433464FD5$46443138394FD5$38424145344FD5$39423131354FD5$46364342314FD5$45324137434FD5$31414233434FD5$34433235364FD5$31324135314FD5$39303335464FD5$31384642334FD5$42313735324FD5$38423341454FD5$43414633444FD5$34383045394FD5$38424638414FD5$36333544414FD5$46393734454FD5$30303133354FD5$33354432334FD5$31453442374FD5$35423243334FD5$38423830344FD5$43374145344FD5$44323636414FD5$33374233364FD5$46324335354FD5$35424633414FD5$39454136414FD5$35384243384FD5$46393036434FD5$43363635454FD5$41453243454FD5$36304632434FD5$44453338464FD5$44333032364FD5$39434334434FD5$45354242304FD5$39303437324FD5$46463942444FD5$32364639314FD5$31394238434FD5$34383446454FD5$36394542394FD5$33344634334FD5$46454544454FD5$44434542414FD5$37393134364FD5$30383139464FD5$42323146314FD5$30463833324FD5$42324135444FD5$34443737324FD5$44423132434FD5$33424544394FD5$34374636464FD5$37303641454FD5$34343131414FD5$35324FD5$7374727563743b7074723b7074723b64776f72643b627974655b383139325d3b627974655b4FD5$5d3b64776f72643b656e647374727563744FD5$4372797074496d706f72744b65794FD5$4372797074446563727970744FD5$464c4152454FD5$4552414c464FD5$437279707444657374726f794b65794FD5$437279707452656c65617365436f6e746578744FD5$437279707444657374726f79486173684FD5$7374727563743b7074723b7074723b64776f72643b627974655b31365d3b656e647374727563744FD5$7374727563743b64776f72643b64776f72643b64776f72643b64776f72643b64776f72643b627974655b3132385d3b656e647374727563744FD5$47657456657273696f6e4578414FD5$456e746572207465787420746f20656e636f64654FD5$43616e2068617a20636f64653f4FD5$4FD5$48656c704FD5$41626f757420436f6465497420506c7573214FD5$7374727563743b64776f72643b64776f72643b627974655b333931385d3b656e647374727563744FD5$696e743a636465636c4FD5$6a75737447656e6572617465515253796d626f6c4FD5$7374724FD5$6a757374436f6e76657274515253796d626f6c546f4269746d6170506978656c734FD5$546869732070726f6772616d2067656e65726174657320515220636f646573207573696e6720515220436f64652047656e657261746f72202868747470733a2f2f7777772e6e6179756b692e696f2f706167652f71722d636f64652d67656e657261746f722d6c6962726172792920646576656c6f706564206279204e6179756b692e204FD5$515220436f64652047656e657261746f7220697320617661696c61626c65206f6e20476974487562202868747470733a2f2f6769746875622e636f6d2f6e6179756b692f51522d436f64652d67656e657261746f722920616e64206f70656e2d736f757263656420756e6465722074686520666f6c6c6f77696e67207065726d697373697665204d4954204c6963656e7365202868747470733a2f2f6769746875622e636f6d2f6e6179756b692f51522d436f64652d67656e657261746f72236c6963656e7365293a4FD5$436f7079726967687420c2a920323032302050726f6a656374204e6179756b692e20284d4954204c6963656e7365294FD5$68747470733a2f2f7777772e6e6179756b692e696f2f706167652f71722d636f64652d67656e657261746f722d6c6962726172794FD5$5065726d697373696f6e20697320686572656279206772616e7465642c2066726565206f66206368617267652c20746f20616e7920706572736f6e206f627461696e696e67206120636f7079206f66207468697320736f66747761726520616e64206173736f63696174656420646f63756d656e746174696f6e2066696c6573202874686520536f667477617265292c20746f206465616c20696e2074686520536f66747761726520776974686f7574207265737472696374696f6e2c20696e636c7564696e6720776974686f7574206c696d69746174696f6e207468652072696768747320746f207573652c20636f70792c206d6f646966792c206d657267652c207075626c6973682c20646973747269627574652c207375626c6963656e73652c20616e642f6f722073656c6c20636f70696573206f662074686520536f6674776172652c20616e6420746f207065726d697420706572736f6e7320746f2077686f6d2074686520536f667477617265206973206675726e697368656420746f20646f20736f2c207375626a65637420746f2074686520666f6c6c6f77696e6720636f6e646974696f6e733a4FD5$312e205468652061626f766520636f70797269676874206e6f7469636520616e642074686973207065726d697373696f6e206e6f74696365207368616c6c20626520696e636c7564656420696e20616c6c20636f70696573206f72207375627374616e7469616c20706f7274696f6e73206f662074686520536f6674776172652e4FD5$322e2054686520536f6674776172652069732070726f76696465642061732069732c20776974686f75742077617272616e7479206f6620616e79206b696e642c2065787072657373206f7220696d706c6965642c20696e636c7564696e6720627574206e6f74206c696d6974656420746f207468652077617272616e74696573206f66206d65726368616e746162696c6974792c206669746e65737320666f72206120706172746963756c617220707572706f736520616e64206e6f6e696e6672696e67656d656e742e20496e206e6f206576656e74207368616c6c2074686520617574686f7273206f7220636f7079726967687420686f6c64657273206265206c6961626c6520666f7220616e7920636c61696d2c2064616d61676573206f72206f74686572206c696162696c6974792c207768657468657220696e20616e20616374696f6e206f6620636f6e74726163742c20746f7274206f72206f74686572776973652c2061726973696e672066726f6d2c206f7574206f66206f7220696e20636f6e6e656374696f6e20776974682074686520536f667477617265206f722074686520757365206f72206f74686572206465616c696e677320696e2074686520536f6674776172652e4FD5$7374727563743b7573686f72743b656e647374727563744FD5$7374727563743b627974653b627974653b627974653b656e647374727563744FD5$43726561746546696c654FD5$75696e744FD5$53657446696c65506f696e7465724FD5$6c6f6e674FD5$577269746546696c654FD5$7374727563743b64776f72643b656e647374727563744FD5$5265616446696c654FD5$436c6f736548616e646c654FD5$44656c65746546696c65414FD5$47657446696c6553697a65"
strings = [unhex(x) for x in str_blub.split("4FD5$")]
script = open("script.au3", "r").read()
modified = script
for c in consts:
modified = modified.replace(f"${c}", str(consts[c]))
for idx, v in enumerate(strings):
modified = modified.replace(f"AREHDIDXRGK($OS[{idx+1}])", f"\"{v.decode()}\"")
open("deobfuscated.au3", "w").write(modified)
Running this script on the source code will provide a much better output. Now that’s a real joy.
The cleaned script can be found here: deobfuscated.au3
Analyzing the Script
Now that everything is cleaner, we need to find the entry point of this script. Since we still have hundreds of lines of code, it might not be that easy to find the line of code that is not part of the function. To do this, we used a simple regex search for ^\w+\(\)
. It resulted in two results — first, a call to AREIALBHUYT()
, and second was a call to GUIDELETE()
.
The AREIALBHUYT
begins with defining the GUI we saw when executing the file. Then, it calls a function that drops either a BMP or DLL files to the disk, with a random name (using FILEINSTALL
). We will need to put our hands on these files, for sure. Let’s do this. Run codeit.exe
in a debugger and put a breakpoint on kernel32!WriteFile
. Then, just before WrieFile
returns, catch the created file and backup it. In our case, we got the files ykxuailcqvrqrnjkpvtp.dll
and yoqjgzqopvjqlllsqgzh.bmp
. We will call them dropped.dll
and dropped.bmp
. Opening the BMP image, we can see that this is the image that appears when opening codeit.exe
. One thing caught our eyes when we opened the image in our editor. The pixels in the first rows look “corrupted”. Stego?
Let’s keep this in mind and continue the analysis. Later in the function, an API function from the DLL is called justGenerateQRSymbol
. This looks like a popular QR related DLL, nothing suspicious. Then, we have a call to a function named AREYZOTAFNF
.
The first line in this function is calling AREUZNAQFMN
and sets the returned value to a variable named $FLISILAYLN
. The function AREUZNAQFMN
is very simple:
FUNC AREUZNAQFMN()
LOCAL $FLFNVBVVFI = -1
LOCAL $FLFNVBVVFIRAW = DLLSTRUCTCREATE("struct;dword;char[1024];endstruct")
DLLSTRUCTSETDATA($FLFNVBVVFIRAW, 1, 1024)
LOCAL $FLMYEULROX = DLLCALL("kernel32.dll", "int", "GetComputerNameA", "ptr", DLLSTRUCTGETPTR($FLFNVBVVFIRAW, 2), "ptr", DLLSTRUCTGETPTR($FLFNVBVVFIRAW, 1))
IF $FLMYEULROX[0] <> 0 THEN
$FLFNVBVVFI = BINARYMID( DLLSTRUCTGETDATA($FLFNVBVVFIRAW, 2), 1, DLLSTRUCTGETDATA($FLFNVBVVFIRAW, 1))
ENDIF
RETURN $FLFNVBVVFI
ENDFUNC
It is calling “GetComputerNameA” to get the name of our computer and returns the value. As such, we can rename $FLISILAYLN
to computer_name
. Next, we can see that computer_name
is transformed into a lowercase binary string. Then, the computer name is passed to a function AREGTFDCYNI
and later we can see a sequence of crypto-related functions. Interesting.
$computer_name = BINARY( STRINGLOWER( BINARYTOSTRING($computer_name)))
LOCAL $computer_nameRAW = DLLSTRUCTCREATE("struct;byte[" & BINARYLEN($computer_name) & "];endstruct")
DLLSTRUCTSETDATA($computer_nameRAW, 1, $computer_name)
AREGTFDCYNI($computer_nameRAW)
LOCAL $FLNTTMJFEA = DLLSTRUCTCREATE("struct;ptr;ptr;dword;byte[32];endstruct")
DLLSTRUCTSETDATA($FLNTTMJFEA, 3, 32)
LOCAL $FLUZYTJACB = DLLCALL("advapi32.dll", "int", "CryptAcquireContextA", "ptr", ...[snip]
IF $FLUZYTJACB[0] <> 0 THEN
$FLUZYTJACB = DLLCALL("advapi32.dll", "int", "CryptCreateHash", "ptr", ...[snip]
The function AREGTFDCYNI
is a very interesting function and it looks like it performs bit manipulations on the computer name. Let’s go over it slowly to understand this function. We annotated, commented and renamed some parts for your convenience.
FUNC AREGTFDCYNI(BYREF $computer_name)
; Create a random name for the BMP image (we used "dropped")
LOCAL $filename = "dropped.bmp"
; Get handle to the BMP file
LOCAL $bmp_file_handle = CreateFile_($filename)
IF $bmp_file_handle <> -1 THEN
; Get the size of the BMP file
LOCAL $file_size = GetFileSize($bmp_file_handle)
; Check if the file size is valid
; and the size of computer name is smaller than file_size - 54
IF $file_size <> -1 AND DLLSTRUCTGETSIZE($computer_name) < $file_size - 54 THEN
; Create a buffer for the file
LOCAL $buffer = DLLSTRUCTCREATE("struct;byte[" & $file_size & "];endstruct")
; Read the file to the created buffer
LOCAL $success = ReadFile($bmp_file_handle, $buffer)
IF $success <> -1 THEN
As shown above, the program reads the dumped BMP file, and checks the length of the computer name. Then we have some simple stego that we will explain.
; Read bytes from the image starting at offset 54
LOCAL $image_data = DLLSTRUCTCREATE("struct;byte[54];byte[" & $file_size - 54 & "];endstruct", DLLSTRUCTGETPTR($buffer))
LOCAL $j = 1
LOCAL $results = ""
; Loop to iterate over every character in the computer name
FOR $computer_name_index = 1 TO DLLSTRUCTGETSIZE($computer_name)
; Take one char from the computer name
LOCAL $char_from_computer_name = NUMBER( DLLSTRUCTGETDATA($computer_name, 1, $computer_name_index))
; Loop 7 times per each char, starting from 6
FOR $index = 6 TO 0 STEP -1
; Take one byte from the image
; Perform logical AND on it to see if the last bit is 1
; Shift it left 1*index times
; Add the value to the original char
$char_from_computer_name += BITSHIFT( BITAND( NUMBER( DLLSTRUCTGETDATA($image_data, 2, $j)), 1), -1 * $index)
$j += 1
NEXT
; Append the char results to "$results"
$results &= CHR( BITSHIFT($char_from_computer_name, 1) + BITSHIFT( BITAND($char_from_computer_name, 1), -7))
NEXT
DLLSTRUCTSETDATA($computer_name, 1, $results)
If you followed the comments, you saw that it looks like simple steganography operations in which every 7 bytes in the image transformed to 7 bits and added to the char of the computer name. These operations on the computer name will give us a new value. That said, if every character in our computer name will have the exact same value as the 7 bits from the image, then the result will stay the same. This is thanks to the AND operations.
Decoding the Computer Name
So what is the value that is hidden in the image? Let’s try to figure it out using python. First, we want to see what are the values used by the program, starting from offset 54.
data = open("dropped.bmp", "rb").read()
print(data[54:200].hex())
# Results
# 'fffffefefefefffffffffefffefffffffffefffefefefffffefefefefefffffefefefffffffffefffefefffffefefffffefffffefefefefffffffefffffffefefffffefefefffefffffffefefffefffffffefefffefffffffefeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
It seems like it contains sequences of 0xff and 0xfe. This makes sense as the program checks the last bit of every byte. Now we can operate on this data and find the computer name
from malduck import chunks
# Read the BMP image from offset 54. We used 150 as an arbitrary limit
data = open(r"dropped.bmp", "rb").read()[54:150]
# Transfer each byte to either '1' or '0' by ANDing it with 1
binary = "".join([str(bit & 1) for bit in data])
# Transform every 7 bits to a character and concatenate them together
mask = "".join([chr(int(x,2)) for x in chunks(binary, 7)])
# Print the results
print(mask)
# Results
# aut01tfan1999
We found “aut01tfan1999”! Now we can set our computer name to “aut01tfan1999”, restart it and start the program. Now we can enter everything we want and check the QR code.
We submit this QR Code to a QR reader and get the flag!
L00ks_L1k3_Y0u_D1dnt_Run_Aut0_Tim3_0n_Th1s_0ne!@flare-on.com