{"author":{"name":null,"type":"card","url":"/"},"content":{"html":"\u003cp\u003eWhile analyzing a sample of \u003ca href=\"https://malpedia.caad.fkie.fraunhofer.de/details/win.castleloader\"\u003eCastleLoader\u003c/a\u003e I decided to test out \u003ca href=\"https://github.com/mandiant/flare-emu\"\u003eflare-emu\u003c/a\u003e an\nemulator based on \u003ca href=\"https://github.com/unicorn-engine/unicorn\"\u003eUnicorn\u003c/a\u003e. Here are a few notes I want to keep for future reference.\u003c/p\u003e\n\u003cp\u003eFor this experiment, the following sample was used: \u003ca href=\"https://bazaar.abuse.ch/sample/39addeb849aa7bd86dd08c260d5cb1d9e28bb5b194d7739341f99d816d8b61ca/\"\u003esha256: 39addeb849aa7bd86dd08c260d5cb1d9e28bb5b194d7739341f99d816d8b61ca\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eThe string obfuscation is fairly straightforward; the obfuscated data is constructed directly on the stack:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-nil\" data-lang=\"nil\"\u003e.text:00197730 33 C0                                   xor     eax, eax\n.text:00197732 C7 45 88 68 00 71 00                    mov     [ebp+var_78], 710068h\n.text:00197739 C7 45 8C 3D 00 32 00                    mov     [ebp+var_74], 32003Dh\n.text:00197740 33 C9                                   xor     ecx, ecx\n.text:00197742 C7 45 90 3A 00 2A 00                    mov     [ebp+var_70], 2A003Ah\n.text:00197749 C7 45 94 66 00 7B 00                    mov     [ebp+var_6C], 7B0066h\n.text:00197750 C7 45 98 34 00 2B 00                    mov     [ebp+var_68], 2B0034h\n.text:00197757 C7 45 9C 78 00 77 00                    mov     [ebp+var_64], 770078h\n.text:0019775E C7 45 A0 39 00 2B 00                    mov     [ebp+var_60], 2B0039h\n.text:00197765 C7 45 A4 78 00 73 00                    mov     [ebp+var_5C], 730078h\n.text:0019776C C7 45 A8 33 00 2B 00                    mov     [ebp+var_58], 2B0033h\n.text:00197773 C7 45 AC 7A 00 70 00                    mov     [ebp+var_54], 70007Ah\n.text:0019777A C7 45 B0 2F 00 76 00                    mov     [ebp+var_50], 76002Fh\n.text:00197781 C7 45 B4 2C 00 30 00                    mov     [ebp+var_4C], 30002Ch\n.text:00197788 C7 45 B8 76 00 6C 00                    mov     [ebp+var_48], 6C0076h\n.text:0019778F C7 45 BC 2A 00 27 00                    mov     [ebp+var_44], 27002Ah\n.text:00197796 66 89 45 C0                             mov     [ebp+var_40], ax\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eThe deobfuscation routine then relies on a basic XOR loop:\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-nil\" data-lang=\"nil\"\u003e.text:001977A0                         unxor_loop:                             ; CODE XREF: sub_197400+3BD↓j\n.text:001977A0 8B C1                                   mov     eax, ecx\n.text:001977A2 83 E0 03                                and     eax, 3\n.text:001977A5 0F B6 80 18 0A 1C 00                    movzx   eax, ds:byte_1C0A18[eax]\n.text:001977AC 66 33 44 4D 88                          xor     ax, word ptr [ebp+ecx*2+var_78]\n.text:001977B1 66 89 84 4D 4C FF FF FF                 mov     [ebp+ecx*2+var_B4], ax\n.text:001977B9 41                                      inc     ecx\n.text:001977BA 83 F9 1D                                cmp     ecx, 1Dh\n.text:001977BD 72 E1                                   jb      short unxor_loop\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eTo emulate this using \u003ccode\u003eflare-emu\u003c/code\u003e, I wrote the Python snippet below.\nInitially, the emulation failed because I didn\u0026rsquo;t account for the required stack frame size.\u003c/p\u003e\n\u003cp\u003eTo fix this, I had to manually allocate a larger stack frame by adjusting the \u003ccode\u003eebp\u003c/code\u003e and \u003ccode\u003eesp\u003c/code\u003e registers.\nBecause the x86 stack grows downwards, establishing this safe workspace requires two steps:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003ccode\u003eebp = sp + 0x400\u003c/code\u003e establishes a safe starting line.\nBy moving the Base Pointer higher in memory, it prevents the emulated code from accidentally overwriting existing stack data.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e\u0026quot;esp\u0026quot;: ebp - 0x600\u003c/code\u003e defines the actual size of the frame.\nSubtracting 0x600 carves out extra bytes of usable stack space between the base pointer and the new top of the stack.\u003c/li\u003e\n\u003c/ol\u003e\n\u003c!--listend--\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e 1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 4\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 5\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 6\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 7\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 8\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e 9\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e10\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e11\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e12\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e13\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e14\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e15\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e16\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kn\"\u003efrom\u003c/span\u003e \u003cspan class=\"nn\"\u003eflare_emu\u003c/span\u003e \u003cspan class=\"kn\"\u003eimport\u003c/span\u003e \u003cspan class=\"n\"\u003eEmuHelper\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eSTART\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mh\"\u003e0x197730\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eEND\u003c/span\u003e   \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"mh\"\u003e0x1977BF\u003c/span\u003e          \u003cspan class=\"c1\"\u003e# instruction AFTER the loop (the lea), NOT the jb at 0x1977BD\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eeh\u003c/span\u003e  \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eEmuHelper\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003esp\u003c/span\u003e  \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eeh\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egetRegVal\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;esp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"c1\"\u003e# need to retrieve the actual value set by Unicorn\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eebp\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003esp\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mh\"\u003e0x400\u003c/span\u003e          \u003cspan class=\"c1\"\u003e# increase the stack base size here\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eeh\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eemulateRange\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"n\"\u003eSTART\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"n\"\u003eendAddr\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"n\"\u003eEND\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"n\"\u003eregisters\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;ebp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eebp\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;esp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eebp\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"mh\"\u003e0x600\u003c/span\u003e\u003cspan class=\"p\"\u003e})\u003c/span\u003e       \u003cspan class=\"c1\"\u003e# her\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eraw\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eeh\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egetEmuBytes\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eebp\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e \u003cspan class=\"mh\"\u003e0xB4\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e29\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e \u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e                  \u003cspan class=\"c1\"\u003e# var_B4, 29 wide chars\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nb\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eraw\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003edecode\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;utf-16-le\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eerrors\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;replace\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003esplit\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"se\"\u003e\\x00\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)[\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e])\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cp\u003eThe output of the decoded strings is: \u003ccode\u003e'http://94.159.113.32/service\\x00'\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eHere are a few other useful functions I noted down while experimenting with the plugin:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003esp\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eeh\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egetRegVal\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;esp\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nb\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sa\"\u003ef\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Stack Pointer is at: \u003c/span\u003e\u003cspan class=\"si\"\u003e{\u003c/span\u003e\u003cspan class=\"nb\"\u003ehex\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003esp\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eTo read data from the stack using the pointer\nFirst option is to read a pointer-sized value (4 bytes on 32-bit, 8 bytes on 64-bit)\nThis is useful for grabbing variables, arguments, or return addresses\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003etop_of_stack\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eeh\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egetEmuPtr\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003esp\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nb\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sa\"\u003ef\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Value at top of stack: \u003c/span\u003e\u003cspan class=\"si\"\u003e{\u003c/span\u003e\u003cspan class=\"nb\"\u003ehex\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003etop_of_stack\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eRead a value at an offset (e.g., \u003ccode\u003e[esp + 8]\u003c/code\u003e)\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eoffset_val\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eeh\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egetEmuPtr\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003esp\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nb\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sa\"\u003ef\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Value at ESP+8: \u003c/span\u003e\u003cspan class=\"si\"\u003e{\u003c/span\u003e\u003cspan class=\"nb\"\u003ehex\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eoffset_val\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eRead a chunk of raw bytes from the stack, for reading structs, strings,\nor buffers pushed to the stack\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003estack_buffer\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eeh\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egetEmuBytes\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003esp\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"c1\"\u003e# Reads 16 bytes starting at ESP\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nb\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sa\"\u003ef\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;Raw stack bytes: \u003c/span\u003e\u003cspan class=\"si\"\u003e{\u003c/span\u003e\u003cspan class=\"n\"\u003estack_buffer\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ehex\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eRead a null-terminated string from the stack, useful if a function decrypted\na string directly onto the stack\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003estack_string\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eeh\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003egetEmuString\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003esp\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nb\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sa\"\u003ef\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;String on stack: \u003c/span\u003e\u003cspan class=\"si\"\u003e{\u003c/span\u003e\u003cspan class=\"n\"\u003estack_string\u003c/span\u003e\u003cspan class=\"si\"\u003e}\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","text":"While analyzing a sample of CastleLoader I decided to test out flare-emu an emulator based on Unicorn. Here are a few notes I want to keep for future reference.\nFor this experiment, the following sample was used: sha256: 39addeb849aa7bd86dd08c260d5cb1d9e28bb5b194d7739341f99d816d8b61ca.\nThe string obfuscation is fairly straightforward; the obfuscated data is constructed directly on the stack:\n.text:00197730 33 C0 xor eax, eax .text:00197732 C7 45 88 68 00 71 00 mov [ebp+var_78], 710068h .text:00197739 C7 45 8C 3D 00 32 00 mov [ebp+var_74], 32003Dh .text:00197740 33 C9 xor ecx, ecx .text:00197742 C7 45 90 3A 00 2A 00 mov [ebp+var_70], 2A003Ah .text:00197749 C7 45 94 66 00 7B 00 mov [ebp+var_6C], 7B0066h .text:00197750 C7 45 98 34 00 2B 00 mov [ebp+var_68], 2B0034h .text:00197757 C7 45 9C 78 00 77 00 mov [ebp+var_64], 770078h .text:0019775E C7 45 A0 39 00 2B 00 mov [ebp+var_60], 2B0039h .text:00197765 C7 45 A4 78 00 73 00 mov [ebp+var_5C], 730078h .text:0019776C C7 45 A8 33 00 2B 00 mov [ebp+var_58], 2B0033h .text:00197773 C7 45 AC 7A 00 70 00 mov [ebp+var_54], 70007Ah .text:0019777A C7 45 B0 2F 00 76 00 mov [ebp+var_50], 76002Fh .text:00197781 C7 45 B4 2C 00 30 00 mov [ebp+var_4C], 30002Ch .text:00197788 C7 45 B8 76 00 6C 00 mov [ebp+var_48], 6C0076h .text:0019778F C7 45 BC 2A 00 27 00 mov [ebp+var_44], 27002Ah .text:00197796 66 89 45 C0 mov [ebp+var_40], ax The deobfuscation routine then relies on a basic XOR loop:\n.text:001977A0 unxor_loop: ; CODE XREF: sub_197400+3BD↓j .text:001977A0 8B C1 mov eax, ecx .text:001977A2 83 E0 03 and eax, 3 .text:001977A5 0F B6 80 18 0A 1C 00 movzx eax, ds:byte_1C0A18[eax] .text:001977AC 66 33 44 4D 88 xor ax, word ptr [ebp+ecx*2+var_78] .text:001977B1 66 89 84 4D 4C FF FF FF mov [ebp+ecx*2+var_B4], ax .text:001977B9 41 inc ecx .text:001977BA 83 F9 1D cmp ecx, 1Dh .text:001977BD 72 E1 jb short unxor_loop To emulate this using flare-emu, I wrote the Python snippet below. Initially, the emulation failed because I didn\u0026rsquo;t account for the required stack frame size.\nTo fix this, I had to manually allocate a larger stack frame by adjusting the ebp and esp registers. Because the x86 stack grows downwards, establishing this safe workspace requires two steps:\nebp = sp + 0x400 establishes a safe starting line. By moving the Base Pointer higher in memory, it prevents the emulated code from accidentally overwriting existing stack data. \u0026quot;esp\u0026quot;: ebp - 0x600 defines the actual size of the frame. Subtracting 0x600 carves out extra bytes of usable stack space between the base pointer and the new top of the stack. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from flare_emu import EmuHelper START = 0x197730 END = 0x1977BF # instruction AFTER the loop (the lea), NOT the jb at 0x1977BD eh = EmuHelper() sp = eh.getRegVal(\u0026#34;esp\u0026#34;) # need to retrieve the actual value set by Unicorn ebp = sp + 0x400 # increase the stack base size here eh.emulateRange( START, endAddr=END, registers={\u0026#34;ebp\u0026#34;: ebp, \u0026#34;esp\u0026#34;: ebp - 0x600}) # her raw = eh.getEmuBytes(ebp - 0xB4, 29 * 2) # var_B4, 29 wide chars print(raw.decode(\u0026#34;utf-16-le\u0026#34;, errors=\u0026#34;replace\u0026#34;).split(\u0026#34;\\x00\u0026#34;)[0]) The output of the decoded strings is: 'http://94.159.113.32/service\\x00'\nHere are a few other useful functions I noted down while experimenting with the plugin:\nsp = eh.getRegVal(\u0026#34;esp\u0026#34;) print(f\u0026#34;Stack Pointer is at: {hex(sp)}\u0026#34;) To read data from the stack using the pointer First option is to read a pointer-sized value (4 bytes on 32-bit, 8 bytes on 64-bit) This is useful for grabbing variables, arguments, or return addresses\ntop_of_stack = eh.getEmuPtr(sp) print(f\u0026#34;Value at top of stack: {hex(top_of_stack)}\u0026#34;) Read a value at an offset (e.g., [esp + 8])\noffset_val = eh.getEmuPtr(sp + 8) print(f\u0026#34;Value at ESP+8: {hex(offset_val)}\u0026#34;) Read a chunk of raw bytes from the stack, for reading structs, strings, or buffers pushed to the stack\nstack_buffer = eh.getEmuBytes(sp, 16) # Reads 16 bytes starting at ESP print(f\u0026#34;Raw stack bytes: {stack_buffer.hex()}\u0026#34;) Read a null-terminated string from the stack, useful if a function decrypted a string directly onto the stack\nstack_string = eh.getEmuString(sp) print(f\u0026#34;String on stack: {stack_string}\u0026#34;) "},"name":"Emulating CastleLoader with Flare-Emu 🏰","published":"2026-09-10T00:00:00+02:00","summary":"A quick reference for configuring Unicorn stack frames and emulating a CastleLoader xor loop with the flare-emu plugin.","type":"entry","url":"/notes/flare-emu-castle/"}