Topic created on: August 15, 2008 07:19 CDT by noglorp .
Fairly simplistic:
Call ConvertThreadToFiber prior OEP, and then within the packed code plant calls to CreateFiber (could also be pre-OEP) and SwitchToFiber. If the process is dumped at OEP, the call to SwitchToFiber will cause an access violation.
What makes this a little sexier is that SwitchToFiber contains no calls itself and could be inlined, making it hard to spot/easy to obfuscate. Along with calling CreateFiber in unpacking stub this could require a sharp eye to spot.
Sample code for convenience:
#include <stdlib.h>
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
void __stdcall Test()
{
printf("Inside fiber");
}
void main2()
{
void *f = CreateFiber(0,Test,NULL);
printf("Pre fiber - ");
SwitchToFiber(f);
}
int main()
{
ConvertThreadToFiber(NULL);
main2();
return 0;
}
Alternative call instead of SwitchToFiber, functionally the same (to prevent finding the call by name)
void aSwitchToFiber(void *f)
{
asm (
//fix broken stack from prolog
//wouldn't be necissary if GCC allowed
//__declspec(naked) with x86
"pop %ebp\n"
//begin identical code
"movl %fs:0x18, %edx\n"
"movl %ds:0x10(%edx), %eax\n"
"movl %esp, %ecx\n"
"movl %ebx, %ds:0xB8(%eax)\n"
"movl %edi, %ds:0xB0(%eax)\n"
"movl %esi, %ds:0xB4(%eax)\n"
"movl %ebp, %ds:0xC8(%eax)\n"
"movl %ss:(%esp), %ebx\n"
"add $0x8,%ecx\n"
"movl %ecx, %ds:0xD8(%eax)\n"
"movl %ebx, %ds:0xCC(%eax)\n"
"movl %ds:(%edx), %ecx\n"
"movl %ds:0x8(%edx), %ebx\n"
"movl %ecx, %ds:0x4(%eax)\n"
"movl %ebx, %ds:0xC(%eax)\n"
"movl %ss:0x4(%esp), %eax\n"
"movl %ds:0x4(%eax), %ecx\n"
"movl %ds:0x8(%eax), %ebx\n"
"movl %ds:0xC(%eax), %esi\n"
"movl %ds:0x10(%eax), %edi\n"
"movl %ecx, %ds:(%edx)\n"
"movl %ebx, %ds:0x4(%edx)\n"
"movl %esi, %ds:0x8(%edx)\n"
"movl %edi, %ds:0xE0C(%edx)\n"
"movl %eax, %ds:0x10(%edx)\n"
"movl %ds:0xB0(%eax), %edi\n"
"movl %ds:0xB4(%eax), %esi\n"
"movl %ds:0xC8(%eax), %ebp\n"
"movl %ds:0xB8(%eax), %ebx\n"
"movl %ds:0xCC(%eax), %ecx\n"
"movl %ds:0xD8(%eax), %esp\n"
"jmp *%ecx\n"
);
}
|
Hi,
First of all, I would like to mention that I like the trick very much ;>
I would propose inlining not the SwitchToFiber, but CreateFiber and ConvertThreadToFiber - both can be inlined and the shouldn't give a hint to what they really are (since ConvertThreadToFiber uses only memory allocation, which could be skiped if we use static memory (however I would leave it as is), and CreateFiber uses memory allocation + some stack related stuff that could be rewritten to be a little less functional, yet shorter).
I think that an unconcealed SwitchToFiber call happening after OEP without prior unconcealed calls to ConvertThreadToFiber and CreateFiber would be more surprising (however it's just my opinion ;>).
From another point of view, this trick, after inlining everything related to fibers, we get a trick that could be described as 'setting something before OEP that is used after OEP'. So the trick could be done without involving fibers, it might very well be some function pointer or sth.
Well, but bringing fibers to it makes it a lot more confusing at the first sight ;>
Good work ;> Keep the fire burning ;>
|
About "naked" functions in gcc/g++, I did a little research how can it be done when last doing some project. You can checkout my blog for description. Short version:
int gimme_five(void);
__asm(
".globl __Z10gimme_fivev\r\n"
".globl _gimme_five\r\n"
"__Z10gimme_fivev:\r\n"
"_gimme_five:\r\n"
" movl $5, %eax\r\n"
" ret"
);
|
Thanks, and thanks for the info about naked gcc.
It really pisses me off that they have that restriction :/. They allow naked for embedded architectures, but not for anything else. The reasoning is "you should just use a .s" but I don't think that works with inlining, and is a pain in the ass, not to mention the "just use a .s" argument does not differentiate between embedded architectures and others, so wtf? -_-
PS: -masm=intel is sweet to, considering all disassembly tools for Windows use intel syntax. I've spent ages looking through Gnu manuals without finding that :D
|
Also, if I read that correctly, will GCC still append the header, only the function will still start after the header? Like,
push ebp
mov ebp, esp
gimme_five:
...
|
Yeah, I've looked a lot for the -masm=intel too ;>
As for the header, no ;> Since the function does not exist at C level. The C compiler does nothing with it, it just knows that there is an external function called 'gimme_five'. The function begins to exist at object generation level (which are generated by the assembler, not the compiler), and there are also "linked" at the assembler level (since the assembler knows that such a label (we are not talking about functions any more ;>) exists an where it is ;>).
So the compiler never has a change to append any header. It's a WYSIWYG in the __asm case.
|
I understand.
I was confusing int gimme_five(); __asm(...);
with int gimme_five() { __asm( ... ); }
I didn't know you could use __asm in static context like that, that is cool.
I also found a nice way to use intel syntax for asm.
".intel_syntax" and ".att_syntax" assembler directives can be used any time, but you need to do .att_syntax after your function to switch the assembler back or else it tries to interpet gcc's att asm as intel asm.
|
Oh, thanks for the ".intel_syntax" and ".att_syntax". Didn't stumble upon it earlier ;> Thx ;>
|
Note: Registration is required to post to the forums.
|