crazy decoder

Author: David Zimmer
Date: 11.17.15 - 1:10am

Here is a little drop of awesome to brighten your day.

So I was asked to write a decryptor for this application. All of the strings internally are held in encrypted format, and there is a lot of them. I located the decryptor and figured out the arguments and how it's utilized, but there are 308 sub functions within/below it. ( it uses std::string which makes a giant mess)

I played around for a couple hours playing with variables of the decryption function I thought that it was trying to replicate it but with no results. Finally I decided it would be easier to just utilize the malware's own decryptor function as a library. I've had a couple posts on doing this before usually by extracting it, or mapping it into memory and calling it that way. But this one is just ridiculously complex and it needs all of the code to be initialized already for it to work. Okay so what do you do in a situation like this?

Well since I need the executable to be fully initialized and ready, I'm pretty much going to have to run it with in the executable itself. First I tried modifying the executable to load as a DLL, but in this case that was not possible. So it has to run as an executable.

Okay, so I modified its import table to automatically load my own DLL. Then I went into win main and patched it so that after the executable had been initialized then it would call one of my exports in my DLL. (I could not use DllMain for this since the exe wouldnt be initialized yet)

So now in my DLL, I CreateWindow and start a message pump. My winproc is an IPC server listening for WM_COPYDATA messages. (My favorite IPC technique)

So basically I have turned the virus, into a decryption server. Now I can send the server messages from an external app, it will decrypt them, and send me back a response. All using the viruses own code at my whim. A basic template for this technique is available here.

Between analysis, experimentation, and then implementation this took a day's labor, but that is quite a deal compared to the complexity that I am harnessing and how long it would have taken to work it out any other way.

This is a pretty hard-core example Of the lengths we have to go sometimes to get the data we need. The sad thing is this is still only a fraction of what I need to accomplish. This just helps me analyze it and see what's there. Painful painful stepping stones :-\

Another take on this..similar scenario, but now dealing with a RWE injection, no exe to mod and use, must hijack decoder in existing process. make an injection dll with a public export.

struct lookup{
	int index;
	int hash;

struct lookup lookups[] = 
	{ 0x0 , 0xAAAAAAAA },
	{ -1, -1}

#define EXPORT comment(linker, "/EXPORT:"__FUNCTION__"="__FUNCDNAME__)

void doit() { #pragma EXPORT int (*decoder)(int,int); FILE* f = fopen("c:\\addr.txt", "w"); _asm mov decoder, 0xBBBBBBBB int i = 0; while( lookups[i].index != -1 ){ int api = decoder(lookups[i].index, lookups[i].hash); fprintf(f,"%x,%x\n",lookups[i].hash,api); i++; } fclose(f); MessageBox(0,"complete!","",0); }

I should also note to compile the lookup list was kind of complex, it was not a simple push const push const call decoder, we had to scan the disasm back from each decoder xref to find the pushs, as other instructions were interleaved and sometimes push reg. Otherwise I could have utilized iDbg so set eip various places step over grab eax etc this case..

so we inject the dll, then we look at the module list, find our new one, view names, goto our export, set origin there, set break on end, now we have a file output of hash/api start address map.

now we need to takes those raw addresses and get the api name for them. We generate a binary file from the addresses, and now inject that into the target process as data using ApiLogger. Then we goto that alloc view as long address, and we can extract the api address to name map. Now we can recombin the data and make an ida enum of the values. Yes..its a royal pita, this scenario is much simpler but more manual steps, code worked first try.

In hindsight, I could have simplified several steps and done a virtalalloc in the dll, and written the return results directly to memory, for then olly look/name extraction. Next time around. While the IPC approach was technically cool, this one is probably a good goto going forward. Unless you need to operate on arbitrary data then the IPC is required. Many ways to skin a cat.

Comments: (0)

Leave Comment:
Email: (not shown)
Message: (Required)


About Me
More Blogs
Main Site
64bit IDA Plugins
Twitter Feed
anterior lines
misc news/updates
Decoders again
CDO.Message Breakpoints
SysAnalyzer Updates
SysAnalyzer and Site Updates
crazy decoder
ida js w/dbg
flash patching #2
JS Graphing
packet reassembly
Delphi IDA Plugin
scdbg IDA integration
API Hash Database
Winmerge plugin
IDACompare Updates
Guest Post @ hexblog
TCP Stream Reassembly
SysAnalyzer Updates
Apilogger Video
Shellcode2Exe trainer
scdbg updates
IDA Javascript w/IDE
Rop Analysis II
scdbg vrs ROP
flash patching
x64 Hooks
micro hook
jmp api+5 *2
SysAnalyzer Updates
InjDll runtime config
C# Asm/Dsm Library
Shellcode Hook Detection
Updates II
Java Hacking
Windows 8
Win7 x64
Graphing ideas
.Net Hacking
Old iDefense Releases
hll shellcode
ActionScript Tips
-patch fu
scdbg ordinal lookup
scdbg -api mode
Peb Module Lists
scdbg vrs Process Injection
GetProcAddress Scanner
scdbg fopen mode
scdbg findsc mode
scdbg MemMonitor
demo shellcodes
scdbg download
api hashs redux
Api hash gen
Retro XSS Chat Codes
Exe as DLL
Olly Plugins
Debugging Explorer
Attach to hidden process
JS Refactoring
Asm and Shellcode in CSharp
Fancy Return Address
PDF Stream Dumper
Malcode Call API by Hash
WinDbg Cheat Sheet
GPG Automation