A forum for reverse engineering, OS internals and malware analysis 

Ask your beginner questions here.
 #25165  by Microwave89
 Thu Feb 05, 2015 6:00 pm
Hey km.info

A few weeks ago, I've been experimenting a bit with issuing raw system calls by leveraging the raw Intel syscall instruction 0F05 and an own minimal syscall number table for Win 7 up to Win 10 TP 9901.
I have then been able to create new threads in my own process without a single invocation of ntdll or kernel32 by doing so.

My question now is, is there any malware known which exploits this technique in order to do its evil work?
This might be particular usefull since

- The 400+ accessible system calls (heck, you can even add a 0x1000 to the call number and can have access to even the win32k calls) give you everything you need
- No crypter needed to obfuscate your calls, however, it still should't be too easy to statically track down what's the code's purpose is
- Any usermode hooks trying to implement behavioral analysis won't work I guess and only a few system calls can be intercepted without crippling Patch Guard but there might be possibilities to get a process handle other than surveillable (via PsSetCreateThreadNotifyRoutine/ObRegisterCallbacks) NtOpenProcess/NtDuplicateHandle,
- If used in an exploit, neither ASLR nor EAF will work against 0F05...

Downside clearly is

- The interface numbers WILL change with every release of Windows and you have no chance to track the changes.
- The more Windows versions you're willing to support the more syscall numbers you have to figure out and to hardcode.

And the question of the white side:
What can be done in order to oppose against malwares leveraging this technique?
In UM?
In KM?


Kind Regards

Microwave89
 #25169  by EP_X0FF
 Fri Feb 06, 2015 5:44 am
UM

-Obfuscation.
Useless. Having sysenter, int 2e commands in your code is the best indicator for various Generic* detections. No matter how it morphed AV will get clean enough code dump, depending on AV and how much samples available, so in the end your callgates will be your signatures.

-Bypass anything.
Could work for some cases. For example if you are defeating some protected software that controls it behaviour by primitive user mode splicing. Depends on how defense implemented and how you implement your clean service call. After sysexit code will go to KiFastSystemCallRet which also can be hooked for PostServiceProcessing. Address of syscall/syscallret can be globally replaced.

-Compatibility and reliability.
From usage in normal program - no this is forbidden. Building your application on pure syscalls will reduce compatibility to zero, produce various undeterminated behaviour cases, and will be complete wasting of time developing this and debugging next trying to figure out where it fucked up.

KM
Useless.
Your syscall will go to the Nt service, that can be hooked in table. Bypass failure. If you want to do "hardcore" clean service call - reimplement Nt service or use it from clean loaded and configured copy of ntos image.

Malware usage
Yes, some use this. Mostly few API's. Example usermode Gootkit trash.

Conclusion:

Useless in most cases. Only for very specific usage, targetting only special cases and only in special software.
 #25170  by TurlaBoy
 Fri Feb 06, 2015 5:45 am
Calling syscalls directly(using sysenter/syscall) is the most efective way to bypass any sandbox implementations in ring3(useless pieces of crap), both PsSetCreateThreadNotifyRoutine/ObRegisterCallbacks can be bypassed by poisoning a single variable into kernel .data this means 2 things, first, 99.9% of malware seen in wild are coded by noobs that does tons of crap, second, if you have a brain you can bypass pretty much everything with a very litlle efford because security solutions are made by more noobs that only do pieces of shit code
 #25177  by TheExecuter
 Fri Feb 06, 2015 8:55 am
haha, i wish i could.
don't need the code actually. This is what he does for x86.
working:
list all exports of ntdll.dll
if first two characters of api offset are Nt,
then calculate address by walking EAT
and place that address in a list.
After list is populated, sort them in ascending order of their addresses.
starting address is syscall 1 and so on we can calculate any syscall NO
from just its address.
 #25178  by EP_X0FF
 Fri Feb 06, 2015 9:22 am
Code: Select all
pfn = GetProcAddress(hNtdll, NtServiceName);
if (pfn) {
#ifdef _WIN64
	c = 4; 
#else
	c = 1; 
#endif
	ServiceIndex =  *(ULONG *)((BYTE *)pfn + c);
}
 #25179  by t4L
 Fri Feb 06, 2015 9:44 am
TheExecuter wrote:haha, i wish i could.
don't need the code actually. This is what he does for x86.
working:
list all exports of ntdll.dll
if first two characters of api offset are Nt,
then calculate address by walking EAT
and place that address in a list.
After list is populated, sort them in ascending order of their addresses.
starting address is syscall 1 and so on we can calculate any syscall NO
from just its address.
Too much work for just a small simple thing
Code: Select all
#ifdef _WIN64
#define SERVICE_ORD(x) (((PBYTE)(x))[4])
#else
#define SERVICE_ORD(x) (((PBYTE)(x))[1])
#endif
NOTE: link your program to appropriate ntdll.lib.
 #25180  by TheExecuter
 Fri Feb 06, 2015 9:58 am
@0xFF: NtServiceName is not available in ntdll.dll for windows 7 x64
@t4l: i dont recognize that structure due to my limited knowledge in KM. But i am sure what OP wanted was not to call Any API and still get value for EAX during syscall in UM.
 #25182  by EP_X0FF
 Fri Feb 06, 2015 10:01 am
NtServiceName is ANSI string name of procedure, e.g. "NtOpenProcess".