Decoders again


Author: David Zimmer
Date: 08.27.16 - 2:50am



Turns out I have allot to say on the topic of writing off hand decoders. We have discussed using an array of bytes black box as char buffers, loading entire exes/dlls in memory, running byte blobs in scdbg for emulation, patching function offsets into blobs, directly using the disasm from IDA in Visual Studio, turning a virus into your own private IPC decoder service etc.

Today I will cover another quick and dirty technique using _emit

So I had a decoder to rip from a malware today. First I tried the hexrays decompilation output as C, VS complained. Ok, then I switched over to using an exported asm dump of the function and _asm. VS complained. Some fidgeting is expected, but I was in a rush and just didnt have time to play with it.

If it was a standalone function I would just call it directly from a function pointer to a byte buffer, but there was one relative call to a compiled in version of memcpy
E8 CB 06 00 00   call    _memcpy
I could expand the buffer and include my own asm opcodes for
B8 B31D907C    MOV EAX, memcpy
FFD0           CALL EAX
this gives me the hardcoded offset I can latter patch at runtime with the actual address of memcpy (here 0x7C901DB3), but again, time is limited and I just didnt feel like the hassle.

what I wanted was a way to just declare a C function, have it spit out all the bytes I wanted, and somewhere in the blob I could just add my inline asm call memcpy. Thats easier and quicker than making my own asm call and patching in the address at runtime right?

Ok, so how do you do this? Welcome to the world of _asm _emit

int __declspec(naked) decoder(char* buf, int sz, unsigned int key)
{
 	_asm _emit 0x55 _asm _emit 0x8B ...
        ...
	_asm call memcpy
        ...
	_asm _emit 0xC3
}


Pretty easy. Now you dont have to fight with the compiler at all. Your still running it as a black box, and function calls will always link right. Downside, you have to debug it in olly and you dont really want to have to change bytes this way, but if you are ripping functions like this, its already a known working thing. Just make sure your prototypes and arguments are correct.

So now, we need an easy way to generate the emit buffers. For this I made a couple small idajs scripts. The first one just dumps a compact emit blob of the byte codes. The second one dumps the disasm and the opcodes on individual lines for easy editing.

Enjoy.

//emit_cur_func.idajs
ea = ida.screenEA()
funcIndex = ida.funcIndexFromVA(ea)
if(funcIndex == -1) throw("Cursor not in a function: ea="+h(ea)+" i="+funcIndex);

fName = ida.functionName(funcIndex);
fStart = ida.functionStart(funcIndex);
fEnd = ida.functionEnd(funcIndex);

tmp = '';j=0;x = new Array();
x.push("// opcodes for " + fName + " size: 0x" + h(fEnd-fStart) + " bytes\r\n");

for(i = fStart; i < fEnd; i++){
    tmp+= "_asm _emit 0x" + h(ida.readByte(i)) + " ";
    j++;
    if(j == 6){
        x.push('\t'+tmp);
        tmp = '';
        j=0;
    }
}

if(tmp.length > 0) x.push('\t'+tmp);
x.push(' }');
x = x.join('\r\n')
app.setClipboard(x)
t(x)




//emit_with_disasm.idajs
ea = ida.screenEA()
funcIndex = ida.funcIndexFromVA(ea)
if(funcIndex == -1) throw("Cursor not in a function: ea="+h(ea)+" i="+funcIndex);

fName = ida.functionName(funcIndex);
fStart = ida.functionStart(funcIndex);
fEnd = ida.functionEnd(funcIndex);

tmp = '';x = new Array();
x.push("// opcodes for " + fName + " size: 0x" + h(fEnd-fStart) + " bytes");

i = parseInt(fStart); //duk takes i as string if not weird..
while(i < fEnd){  
    sz = ida.instSize(i);
    if(sz < 1){
        alert("Inst size 0 @ "+h(i));
        break;
    }
    for(j = 0; j < sz; j++){    
        tmp+= "_asm _emit 0x" + h(ida.readByte(i+j)) + " ";
    }
    tmp = padAsm(i) + tmp;
    
    i+=sz;
    x.push('\t'+tmp);
    tmp = ''
}

x = x.join('\r\n')
app.setClipboard(x)
t(x)

function padAsm(va){
   defLen = 45;
   asm = ida.getAsm(va);
   a = asm.indexOf(';'); //ida strip comments
   if(a > 0) asm = asm.substring(0,a);
   while(asm.length < 30) asm+=' ';
   asm = "/* " + asm + " */  "
   return asm;
}


Example output:

1)
// opcodes for decoder size: 0xD3 bytes
 	_asm _emit 0x55 _asm _emit 0x8B _asm _emit 0xEC _asm _emit 0x83 _asm _emit 0xEC _asm _emit 0x0C 
	_asm _emit 0x6A _asm _emit 0x04 _asm _emit 0x8D _asm _emit 0x45 _asm _emit 0x10 _asm _emit 0x50 

2)
// opcodes for decoder size: 0xD3 bytes
	/* push    ebp                    */  _asm _emit 0x55 
	/* mov     ebp, esp               */  _asm _emit 0x8B _asm _emit 0xEC 
	/* sub     esp, 0Ch               */  _asm _emit 0x83 _asm _emit 0xEC _asm _emit 0x0C 





Comments: (1)

On 08.27.16 - 7:50am Dave wrote:
the second script is actually a really convenient way to edit the code, you dont have to worry about the details of the byte blob and making VS happy with its disasm syntax, and you can still edit exactly the portions you want inline without trying to insert code using copymemory calls

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



Twitter
RSS

About Me
More Blogs
Main Site
Posts:
64bit IDA Plugins
Twitter Feed
anterior lines
misc news/updates
KANAL Mod
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
findDll
Java Hacking
Windows 8
Win7 x64
Graphing ideas
.Net Hacking
Old iDefense Releases
BootLoaders
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