pkr_ce1a : An unknown packer?

0x00: Contents

Elemental X
8 min readFeb 28, 2023
  • Introduction.
  • File Overview.
  • Static Analysis.
  • Identifying Unpacking routine.

0x01: Introduction:

Hi people, I hope everyone is doing great! As, I am slowly learning to analyze unknown malware samples, decided to apply my little existing analysis skills against an unknown packer known as Zenpack or pkr_ce1a, which is a first stage ITW payload from this malicious URL or C2, dropping Smokeloader loader in the target machine as per a blog by guys at Malwarology . Although, I wanted to get more familiar with understanding with SmokeLoader and it’s working, but keeping in mind I suck pretty bad manually unpacking unknown packers, I will go with this packer this time. My blog will be pretty relevant with the one by guys at Malwarology, so complete credit goes to them. This blog is just my way of learning and noting while mimicking methods of analysis by guys at Malwarology. Please let me know, if you find something dumb.

0x02: File Overview:

At, first we start our analysis by loading the file into CFF Explorer which gives a very small overview of the file. Now, let us inspect some attributes of this file .

The very basic info about this file is this version of Microsoft Visual C++ used to compile the executable file being loaded.

Then, after checking the file header structure of this PE File, it turns out that it has 4 sections just a normal binary, there is a UNIX time stamp which evaluates to the value that, at which time the program is compiled, the value in this field is 620CCE88, which again evaluates to May 25, 2022, thanks to online converter. Also, a straight-up evaluation is this file is a 32-bit file.

Then, we jump ahead to the section headers, looking for abnormal section headers like we have in normal common packers like UPX and ASPack. Anyways this one looks pretty normal, as per my little knowledge base.

Now, coming to the import directory, this looks kind of pretty suspicious as there are very less number of imports.

Now coming to the resources section , we see we have weird sections, which contains some weird gibberish, we will keep that for now, and load this file in PEiD to check for known crypto algorithms and other information, if we are able to find something new.

After, loading the sample into CAPA and PeiD and analyzing with KANAL tool, we can confirm that TEA or Tiny Encryption Method has been used to encrypt some content, looking up in the internet, at the very beginning, I tried to look ahead for specific Windows APIs being used to implement that, but unfortunately I could not find any, and then I looked for certain constants according to some YARA rules which have added some constant, but unfortunately, I could not come to an conclusion, anyways we will try to figure that out in the static analysis section.

0x02: Static Analysis

In the previous sections, we figured out the basic overview of the file. Now it’s time to load the file in IDA and figure out the binary using its disassembly until it makes some sense, and for this I will shamelessly take help of the blog written by guys at malwarology, so let us get started without a further delay.

Once, the initial analysis is complete, we jump to the main function and get the disassembly, then we can see that a value 0x0FFF5C925 is being moved inside eax, then the value of eax register is copied to a DWORD which is again used as a argument for LocalAlloc _0 as per the disassembly.

That’s why it’s better to be renamed as arg-for_localloc_0 then we can see that using LoadLibraryW kernel32.dll is loaded and the base address of the loaded module that is kernel32.dll is assigned to a variable called dword_42D5D0 . Next, we can see that a variable called LocalAlloc_0 is retrieving the base address for LocalAlloc Windows API using GetProcAddress whose function definition is as follows:

FARPROC GetProcAddress(
[in] HMODULE hModule,
[in] LPCSTR lpProcName
);

where lpProcName is the function name “LocalAlloc” and a handle to the DLL module that is KERNEL32.DLL which was stored i the variable dword_42D5D0 and in simple words LocalAlloc_0 is now the brand new LocalAlloc.

Therefore, we can come to a small amount of conclusion that a certain address, was allocated using LocalAlloc(), then we have another function, known as sub_4058C8 being called, now let us check out the other function.

Now, this time we check out de compiled code view from IDA

It clearly summarizes that, it is loading an Windows API known as VirtualProtect and it is using using the same technique to load it and store it in a variable dword_42D538 , then we can see four arguments being passed on to VirtualProtect which was loaded in the variable.

At first, let us check out the function VirtualProtect.

BOOL VirtualProtect(
[in] LPVOID lpAddress,
[in] SIZE_T dwSize,
[in] DWORD flNewProtect,
[out] PDWORD lpflOldProtect
);

Now, here dword_42D540 is the address which is to be changed, then dwSize turns out the same variable which was passed to LocalAlloc, so it means there is a certain memory section which is supposed to be a shellcode am assuming till now, and the flNewProtect is the current version which is now changed to 0x40 which means the newly allocated memory now holds (PAGE_EXECUTE_READWRITE) permissions, and it is then called called back to the WinMain function.

Just after that, we have another function being called, known as sub_40597D now let us check out what actually it is doing.

The very block of disassembly shows that it is setting up an exception handler, and then it jumps to this label loc_405A4F

now, here it is comparing it with the variable shellcode_size with a decimal 22 . Then it jumps to another label from that label which is loc_405AA5 .

Then, after jumping to this label, there is a for loop which keeps on running I.e., it jumps to loc_405AF3 which then keeps on allocating the encoded data present in .data section to a newly allocated section.

This allocation can be visualized by setting a breakpoint just before the loop and synchronizing the hexdump with the register eax which can help us to visualize multiple .data sections being moved into a new allocated memory.

While debugging, the EIP is never transferred to this block of code.

After, the shellcode has a newly allocated memory, it then calls a function, which also takes, shellcode size and lpAddress as an argument. Then going forward it has some sets of Windows APIs which are never used, or the EIP never jumps to those sets of functions.

Then, this block of code or function which we can name as decode calls another function, which involves a constant known as 0x9E3779B9 which is a constant called Delta and is used in Tiny Encryption Algorithm or TEA which was first pretty confusing for us, this function probably decodes the encoded data and pushes the blob in the allocated region or lpAddress

Now, after the decode function is done executing, we have a small loop which compares a value 770E inside ecx register, and then jumps to a certain label loc_406493 , where the value of ecx is increased by one and then compared with another constant 0x286B97D and again jumps to the same address. Keeping in mind the disassembly, where the values inside register ecx was xor’d. It is just supposed to waste analysis time by addition of this loop. So, it is better to patch this loop and just move the function which we can see in the graph that is sub_4058AE .

int sub_4058AE()
{
int result; // eax

result = 15345;
lpAddress = (char *)lpAddress + 15345;
return result;
}

In this function, we can see a constant value being added to the address where the decoded blob is present that is lpAddress . After all this the exception handler is reset, and this function is wrapped up with a call to LoadLibrary which hardly makes any sense.

With this, the unpacking routine ends, and the control is transferred back to the WinMain() function.

On execution, it connects back to internet, and the dropped file which is smokeloader payload is dropped at Appdata/ folder.

0x03: Identifying Major routines

In this sample, the major routines were the ones loading the encoded shellcode to a newly allocated address, another important routine was the one decoding the encoded chunks using TEA symmetric encryption-decryption technique which was identified using the delta constant, and the last one was, the one which was fixing the OEP of the shellcode which I renamed to lpAddress by adding a constant. Technically speaking, I did not add much of the debugging part, but thanks to guys at malwarology, I was able to trace through the program and identify anti-analysis loops saving a lot of time while tracing and figuring out the disassembly. The entire credit goes to them. If you find anything wrong please don’t hesitate to contact me via my discord tag ElementalX#3463 .

--

--