| View previous topic :: View next topic |
| Author |
Message |
Polynomial Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 524 Location: Inside the Intel CET shadow stack
|
Posted: Mon Aug 10, 2009 4:54 pm Post subject: Runtime code generation from buffer, then jmp |
|
|
I had an idea about putting a block of machine code in a buffer, then use inline ASM to jump to the location of that buffer and execute it as normal code. Is that possible?
For example:
| Code: | void main() {
// Define the payload buffer with a RETN at the end
unsigned char payload[] = {0x90, 0x90, 0x90, 0x90, [...], 0xC2};
// Find the address of the buffer in memory
DWORD payloadAddress = (unsigned long) &payload;
__asm {
jmp DWORD PTR payloadAddress
}
cout << "Done.";
} |
I've tried it, but it doesn't seem to work. My program never reaches the cout << "Done"; line.
Any ideas?
|
|
| Back to top |
|
 |
Deltron Z Expert Cheater
Reputation: 1
Joined: 14 Jun 2009 Posts: 164
|
Posted: Mon Aug 10, 2009 5:06 pm Post subject: |
|
|
Of course it's possible... the code will be translated to machine code anyway so it's basically the same thing, except you're executing data which anti-viruses usually mark as suspicious without even executing it in the sandbox.
An easier way would simply write the function normally in the data section if that's what you really want... packers and protectors change the PE header and the sections to trick debuggers like OllyDBG, by doing so olly gets confused and can't analyze the code properly since it thinks it's data (so NOP would look like db 90 instead) and even make it crash.
|
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 475
Joined: 09 May 2003 Posts: 25973 Location: The netherlands
|
Posted: Mon Aug 10, 2009 5:14 pm Post subject: |
|
|
Will cause errors on systems that have the no execute bit set
It's easier to just call VirtualAlloc, copy the buffer, and then jump to there
_________________
Tools give you results. Knowledge gives you control.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
Polynomial Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 524 Location: Inside the Intel CET shadow stack
|
Posted: Mon Aug 10, 2009 5:22 pm Post subject: |
|
|
Well I kinda figured NX would mess it up.
How would I use VirtualAlloc to do something like this?
|
|
| Back to top |
|
 |
Deltron Z Expert Cheater
Reputation: 1
Joined: 14 Jun 2009 Posts: 164
|
Posted: Mon Aug 10, 2009 6:05 pm Post subject: |
|
|
| Allocate enough memory with execute access, there are better ways though...
|
|
| Back to top |
|
 |
Polynomial Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 524 Location: Inside the Intel CET shadow stack
|
Posted: Mon Aug 10, 2009 6:33 pm Post subject: |
|
|
Noz3001 has been helping me on IRC, but we're stuck. Here's what I have:
| Code: | #include <windows.h>
#include <stdio.h>
#include <iostream.h>
void main()
{
unsigned char payload[] = { 0x90, 0x90, 0x90, 0xC2 };
int mem_size = 1024;
LPVOID ptr = VirtualAlloc(NULL, (DWORD) mem_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
DWORD *oldProtect = 0;
BOOL ok = VirtualProtectEx(GetCurrentProcess(), ptr, (DWORD) mem_size, PAGE_EXECUTE_READWRITE, oldProtect);
if(ok != TRUE)
{
cout << "VirtualProtect failed.\n";
}
memcpy(ptr, payload, 5);
void* (*payloadCall)() = (void* (__cdecl *)(void)) &ptr;
payloadCall();
cout << "Done.\n";
} |
I get an access violation on payloadCall().
Things we've tried:
memcpy with length 4
Replacing __cdecl with __stdcall
Altering mem_size
Any ideas?
|
|
| Back to top |
|
 |
hcavolsdsadgadsg I'm a spammer
Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Mon Aug 10, 2009 6:39 pm Post subject: |
|
|
are you living in the stone age?
<iostream.h> and void main()??
|
|
| Back to top |
|
 |
Chaosis13 Master Cheater
Reputation: 0
Joined: 14 Aug 2007 Posts: 372
|
Posted: Mon Aug 10, 2009 7:01 pm Post subject: |
|
|
| You could try creating a thread that starts at that location. I have used this technique for other things... You can also use some ASM to do things when C++ gives you compile errors, like it does with function pointers a lot.
|
|
| Back to top |
|
 |
Polynomial Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 524 Location: Inside the Intel CET shadow stack
|
Posted: Mon Aug 10, 2009 7:04 pm Post subject: |
|
|
slovach - Microsoft Visual C++ 6... 'nuff said.
_________________
It's not fun unless every exploit mitigation is enabled.
Please do not reply to my posts with LLM-generated slop; I consider it to be an insult to my time. |
|
| Back to top |
|
 |
hcavolsdsadgadsg I'm a spammer
Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Mon Aug 10, 2009 8:08 pm Post subject: |
|
|
| Burningmace wrote: | | slovach - Microsoft Visual C++ 6... 'nuff said. |
upgrade? visual studio has a (for all of your purposes at least) fully featured free version.
This should work fine, it goes into the infinite loop as expected
| Code: | #include <Windows.h>
int main()
{
BYTE payload[] = { 0xB8, 0x00, 0x00, 0x02, 0x00, 0xFF, 0xE0 };
//mov eax, 00020000
//jmp eax
SIZE_T mem_size = 1024;
DWORD addy = 0x00020000; //fuuuuuuuuuck
LPVOID ptr = VirtualAlloc((void*)addy, mem_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(ptr, payload, sizeof(payload));
void (*payloadCall)(void);
payloadCall = (void (__cdecl*)(void))ptr;
(*payloadCall)();
return 0;
} |
|
|
| Back to top |
|
 |
BanMe Master Cheater
Reputation: 0
Joined: 29 Nov 2005 Posts: 375 Location: Farmington NH, USA
|
Posted: Mon Aug 10, 2009 9:08 pm Post subject: |
|
|
NtCreateSection(PAGE_FILE!);
NtMapViewOfSection();//with PAGE_EXECUTE_READWRITE..
copy code to mapview then jmp to it.. this also avoids NX bit..
also RtlCreateHeap with a filled out RTL_HEAP_PARAMETERS for the Alloc Compare and Free Routines would also bypass the NX bit..
BanMe
_________________
don't +rep me..i do not wish to have "status" or "recognition" from you or anyone.. thank you. |
|
| Back to top |
|
 |
Polynomial Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 524 Location: Inside the Intel CET shadow stack
|
Posted: Tue Aug 11, 2009 4:05 am Post subject: |
|
|
slovach - I just get an exception again.
I have Visual Studio 2005 Professional, but there's no option for a C++ project, only C#, VB.NET, J# and ASP.
_________________
It's not fun unless every exploit mitigation is enabled.
Please do not reply to my posts with LLM-generated slop; I consider it to be an insult to my time. |
|
| Back to top |
|
 |
Slugsnack Grandmaster Cheater Supreme
Reputation: 71
Joined: 24 Jan 2007 Posts: 1857
|
Posted: Tue Aug 11, 2009 4:10 am Post subject: |
|
|
| BanMe wrote: | NtCreateSection(PAGE_FILE!);
NtMapViewOfSection();//with PAGE_EXECUTE_READWRITE..
copy code to mapview then jmp to it.. this also avoids NX bit..
also RtlCreateHeap with a filled out RTL_HEAP_PARAMETERS for the Alloc Compare and Free Routines would also bypass the NX bit..
BanMe |
don't take this as an attack but what is it with you and using native APIs ?
|
|
| Back to top |
|
 |
Polynomial Grandmaster Cheater
Reputation: 5
Joined: 17 Feb 2008 Posts: 524 Location: Inside the Intel CET shadow stack
|
|
| Back to top |
|
 |
Deltron Z Expert Cheater
Reputation: 1
Joined: 14 Jun 2009 Posts: 164
|
Posted: Tue Aug 11, 2009 6:56 am Post subject: |
|
|
| slovach wrote: | | Burningmace wrote: | | slovach - Microsoft Visual C++ 6... 'nuff said. |
upgrade? visual studio has a (for all of your purposes at least) fully featured free version.
This should work fine, it goes into the infinite loop as expected
| Code: | #include <Windows.h>
int main()
{
BYTE payload[] = { 0xB8, 0x00, 0x00, 0x02, 0x00, 0xFF, 0xE0 };
//mov eax, 00020000
//jmp eax
SIZE_T mem_size = 1024;
DWORD addy = 0x00020000; //fuuuuuuuuuck
LPVOID ptr = VirtualAlloc((void*)addy, mem_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(ptr, payload, sizeof(payload));
void (*payloadCall)(void);
payloadCall = (void (__cdecl*)(void))ptr;
(*payloadCall)();
return 0;
} |
|
What...?
Why are you jumping to 0x20000? what's in there? nothing... the compiler might not even allocate memory in there, addresses are different on different computers, so you should use relative jmps, the simplest infinite loop: 0xEB 0xFE - JMP HERE, simply jmps to the same address this instruction is. (reverse jump)
|
|
| Back to top |
|
 |
|