Contents

Flare-On 7 — 06 Codeit

Challenge Description
Reverse engineer this little compiled script to figure out what you need to do to make it give you the flag (as a QR code).

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.

/posts/flare-on7-codeit/images/image.png

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.

/posts/flare-on7-codeit/images/sparks_joy.gif

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?

/posts/flare-on7-codeit/images/image_1.png

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.

/posts/flare-on7-codeit/images/image_2.png

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