Jump to content











Photo
* * * * * 1 votes

ShellCodeExecGUI


  • Please log in to reply
25 replies to this topic

#1 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 21 December 2011 - 12:02 PM

Posted Image

File Name: ShellCodeExecGUI
File Submitter: joakim
File Submitted: 20 Dec 2011
File Updated: 22 Dec 2011
File Category: Security

This is a GUI for executing machinecode in text form, or as one would say uncompiled shellcode. The application makes use of a trick to execute binaries from memory. What is mapped to memory first, is a standard minimal shellcode executer looking like this;


#include <stdio.h>

#include <string.h>

#include <stdlib.h>



char code[] =   "the shellcode";



int main(int argc, char **argv)

{

	((void (*)())code)();

	

	return 0;

}


However, I compiled it in Visual Studio with 10240 bytes of junk (00's), so the actual executer does absolutely nothing in itself, but can receive as much as 10240 bytes of code. Now we can write our custom shellcode into the right memory location and execute the memory-mapped shellcode executer that now holds our shellcode. Btw, the execute-from-memory trick originates from trancexx; http://www.autoitscr...412-run-binary/ which again probably learned from; http://www.joachim-b...ll-from-memory/

The memory-mapped exe is located inside the GUI as a resource. On the 32-bit version it is named SHELLCODE, and on the 64-bit version named SHELLCODE64 and is of type RCDATA. In the download both these base exe's can be found as empty_x86.exe and empty_x64.exe. Alternatively they could have been embedded in the actual script, but I chose not to.

So there's 3 ways to execute the code:
  • Paste the code directly in the input field and press execute. Code can be in the usual form; "\xFC\x33\xD2\xB2\x30\x64\xFF\x32\x5A\x8B" or "FC33D2B23064FF325A8B". All non-hexadecimal characters are automatically stripped out, so paste the code without any comments.
  • Open and execute a text file with code in the form as specified in #1.
  • Open and execute a binary file containing the shellcode.
Both 32-bit and 64-bit version are included. It has been tested on 32-bit XP and Windows 7, and 64-bit Windows 7, for which it works great. Bear in mind that shellcode usually are very OS dependant, so if something does not work, it is likely the shellcode and not the GUI that is wrong. For some very basic testing I included my own application that implements GetProcAddress. Ie, it will get the address of a given function. Also usually referred to as "arwin.exe". Note that functions are case sensitive.

Debugging shellcode:
Debugging of the code is now implemented and can be configured with a tickbox. What I did was just inserting 0xCC (INT 3) right before the shellcode, or 0x90 if configured off. To debug, JIT debugger obviously must be configured. If using WinDBG it can be set by this command; "windbg -I". What happens then is, the debugger will fire up exactly at the start of the shellcode. Very handy! The debug stuff has been tested OK on 32-bit XP, but I see no reason it should not work on other OS/Arch since 0xCC = INT 3 anyway.. Look at the linked image and you'll see that 0xCC will trigger debugger and that you are right at shellcode start.

Posted Image

The above image really is very descriptive of what is going on in a debug session. Notice how badly formatted shellcode is just pasted in and executed.

More shellcode explanantion might be necessary, but I'm really not very experienced with shellcoding, and am therefore not the right person to. But I think it is a nice way of jumping into it. I am not saying this is something great to have when developing shellcode. I am just saying it might be usefull when getting your hands dirty for the first time, and learning. For instance you have some shellcode that opens a messagebox, but the address is wrong and you want to change it and test without recompiling. Or you have some basic shellcode that executes a Beep or calc.exe, that you want to fiddle with, and expand on. Preferrably run all this inside a virtual machine when testing (highly recommended, but not necessary if you know what you're executing). For some serious tracing, a debugger would be necessary, and for that reason I added an option to do so by means of INT3. This is fun to learn, and sometimes practical testing is a good and funny part of it. I think the easyness of testing modified existing code is appealing here.

Of course one could have compiled a cli executer that would take the textual machinecode as an argument, but that's a different method. Now a few days later I found one at; http://mcdermottcybe...s-x64-shellcode but it will take the shellcode as a binary file, so use use the included text2bin.exe to convert textual hex into binary form. The app's source runbin.c have been compiled into both runbin_x86.exe and runbin_x64.exe. A nice feature on that little app is -d switch for debugging. Also compiled the source shell64.asm on that site. The machine code variant is included as shell64.bin, and can be used to test msgbox shellcode on Windows 7 x64. Its disassembly is included as msgbox64.txt.

The method implemented in the GUI is almost the same as patching an executable on-disk. Except we already know where to inject the code and don't need to worry about cleaning up afterwards. And to clarify, this is NOT about executing exploits! It is about observing what would otherwise happen after an exploit has worked (ie the payload execution in the metasploit world).

Included in the download is a "OS universal" sample written by Berend-Jan "SkyLined" Wever that launches calc.exe, at only 100 bytes of code.

The included text2bin.exe is a handy utility for converting shellcode source into binary. Be sure to have excluded comments and other c source stuff from it so the file only contains;


; "\x2f\xbe\x2f\xd9\x2f\xc7\x2f\xd0\xe7\x9a\xfe\xfe\xfe\x54\x2f\xbe"

; "\x62\x89\x3e\x2e\x83\xbe\x76\x0a\x89\x3e\x0a\x89\x6e\x1a\xab\x89"


or smething like;


FC33D2B23064FF325A8B


Having its binary form is necessary when disassembling it. For that task, ndisasm.exe (included with nasm) is great; http://www.nasm.us/

Example:
Here is some very basic 19 bytes designed for XP SP3 that will execute the Beep function in kernel32.dll;


\x33\xC0\xB8\x8F\x7A\x83\x7C\x68\x00\x04\x00\x00\x68\x00\x03\x00\x00\xFF\xD0


When disassembled look like this;


00401000	 33C0		   XOR EAX,EAX							

00401002	 B8 8F7A837C	MOV EAX,kernel32.Beep				  

00401007	 68 00040000	PUSH 400							  

0040100C	 68 00030000	PUSH 300							  

00401011	 FFD0		   CALL EAX								


Pasting that code in my program, may or may not work. In my case it did not. I have the right OS, but probably wrong language. So I looked up the address of Beep in kernel32 on my system, and noticed;


Found function Beep in module kernel32.dll at address: 0x7C837AA7

Shellcode formatted: \xA7\x7A\x83\x7C


So I replaced "\x8F\x7A\x83\x7C" with "\xA7\x7A\x83\x7C" and tried again, and voila it works. Now looking up the function at msdn; http://msdn.microsof...7(v=vs.85).aspx reviels that PUSH 400 and PUSH 300 pushes the values of dwDuration and dwFreq onto the stack (in the reverse order compared to documentation at msdn). So if we change PUSH 400 to PUSH 8000 and PUSH 300 to Push 870, you would be rather annoyed, especially if suffering tinnitus.

Click here to download this file

#2 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 21 December 2011 - 09:51 PM

Updated to version 3 with configuration for debugging.

I must say it now appears slightly easier to create some lame shellcode after having done this..

#3 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 24 December 2011 - 08:46 AM

I must say this is pretty amazing, this could prove very useful, great contribution :)

I ran the MessageBox bin (binary) file as a test, and it seems to be working

#4 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 28 December 2011 - 09:37 AM

The same thing can be achieved by several different methods. For instance using VirtualAlloc and CallWindowProc will also let you execute code directly. But one of the points about the GUI was to prevent the host process from crashing by running the code under a remote process. So another approach could have been by using CreateThread or CreateRemoteThread.

#5 walli

walli
  • Members
  • 1 posts
  •  
    Canada

Posted 23 January 2013 - 05:59 PM

ShellCodeExecGui v4 is BDS/Shell.AC.299 Trojan Generic. Why only do You do that ?!

(Avira and virustotal.com)



#6 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 23 January 2013 - 06:19 PM

ShellCodeExecGui v4 is BDS/Shell.AC.299 Trojan Generic. Why only do You do that ?!

(Avira and virustotal.com)

 

Well, I don't do that :) The stupid AV engine did.

 

I'll tell you one thing. The program does absolutely nothing if you don't paste any machine code into the input field and execute it. It's an empty GUI then.

 

If you paste code to trigger a beep, then you may get a beep. If you paste code to trigger a message box, then you may get a message box.

 

This is provided that the code pasted actually works on the OS it is executed on.

 

If you paste working machine code for a reverse shell, then you will get that too. Maybe that's why it rated.

 

But a trojan, I don't think so.



#7 Brito

Brito

    Platinum Member

  • .script developer
  • 10616 posts
  • Location:boot.wim
  • Interests:I'm just a quiet simple person with a very quiet simple life living one day at a time..
  •  
    European Union

Posted 23 January 2013 - 09:13 PM

Hi Walli,

 

Joakim is a trusted member on our community for a very long time.

 

:cheers:



#8 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 04 April 2013 - 11:28 AM

Beep(700, 1000);
000007D0  68E803            push word 0x3e8
000007D3  0000              add [bx+si],al
000007D5  68BC02            push word 0x2bc
000007D8  0000              add [bx+si],al
000007DA  FF15              call word [di]

So here's what part of the relevent disassembly looked like from ndisasm... You can see the value for the second param of the Beep function from kernel32.dll being pushed onto the stack (0x3E8 = 1000, for a 1 second duration or 1000ms), as well as the frequency (0x2BC = 700).

I wrote my own C++ program that got the address of the Beep function from kernel32.dll which returned 0x764531AF, which I suspected was \xAF\x31\x45\x76 in shellcode.
 
GetProcAddress(
	GetModuleHandle(L"kernel32.dll"), 
	"Beep"
);

After doing some tests I could not get a beep, so I wondered if this was all accurate information, and it seemed to be confirmed after I ran your AutoIt program to get the address for this function.

I'm using Windows 8 x64 Pro with Media Center. Tested through VS to try some inline asm:
 
 
01258365 A1 B4 12 26 01       mov         eax,dword ptr ds:[012612B4h]
0125836A 68 E8 03 00 00       push        3E8h
0125836F 68 EE 02 00 00       push        2EEh
01258374 FF D0                call        eax

This worked when ran directly in the debugger... Although this is not what I wanted, as that is not a usable address, if I was to convert this to shellcode:
 
dword ptr ds:[012612B4h]

So I tried substituting the actual function address from the kernel32.dll module as 0x764531AF (\xAF\x31\x45\x76) just to see, and no luck still even with putting that address in manually:
009163DA B8 AF 31 45 76       mov         eax,764531AFh  
009163DF 68 E8 03 00 00       push        3E8h  
009163E4 68 EE 02 00 00       push        2EEh  
009163E9 FF D0                call        eax

*Which became this in shellcode:
\xB8\xAF\x31\x45\x76\x68\xE8\x03\x00\x00\x68\xEE\x02\x00\x00\xFF\xD0

edit: NOTE: The inline asm worked for that address. But the shellcode derived from the disassembly did not... Just to clarify.

I tried anyways, because obviously the shellcode above designed for XP SP3, wouldn't work with my Win8 OS. Just thought I would share my experience in this thread, even though it was from an unsuccessful attempt.

#9 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 05 April 2013 - 02:54 AM

Even tried adding \x33\xC0 to the beginning (instruction XOR EDX,EDX) to set EDX to 0, but it did not work. I'm currently trying to set up XP in Hyper-V to do some testing there...

#10 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 06 April 2013 - 08:06 AM

It would/may seem there is an issue with the program... The shellcode I had worked perfectly when I hardcoded and compiled to run it myself. This was tested with v4. I got a Beep :)

I had to add a ret though to avoid a segmentation fault. Any shellcode I tried here though just caused the process to crash.

#11 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 07 April 2013 - 07:23 AM

I understand you attempting a beep. Can you post the code you are trying and also specify the arch and OS of the traget machine? I can take a quick look.



#12 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 07 April 2013 - 07:32 AM

I understand you attempting a beep. Can you post the code you are trying and also specify the arch and OS of the traget machine? I can take a quick look.

The code that I was trying is this string of bytes:
\xB8\xAF\x31\x45\x76\x68\xE8\x03\x00\x00\x68\xEE\x02\x00\x00\xFF\xD0

The process would crash, so after going through a whole bunch of tests, I verified that the address was correct, and the ASM looked fine... I finally created my own program directly in C however to take care of handling all forms of input without any extra binaries for shellcode execution, and which can run the shellcode from a bin file, and as an argument, and that same shellcode works from my program, the only thing it was missing was a ret (to avoid segemtation fault throwing an exception), so I added \xC3 to the end, and no problems at all after that (*from my program anyways*):
 
\xB8\xAF\x31\x45\x76\x68\xE8\x03\x00\x00\x68\xEE\x02\x00\x00\xFF\xD0\xC3

The address at the time of testing: \xB8\xAF\x31\x45\x76\x68\xE8\x03\x00\x00\x68\xEE\x02\x00\x00\xFF\xD0 (0x764531AF for the Beep function in kernel32.dll)

Architecture: Intel x86-64 (64 Bit)
OS: Windows 8 Pro (with Media Center)
 
Note: I can run this same set of instructions from inline ASM in a C++ test program I created in Visual Studio:
__asm
{
	mov eax,dword ptr 0x764531AF // Kernel32.dll!764531AF()
	push 0x3E8                   // Duration argument
	push 0x2EE                   // Frequency argument
	call eax                     // Call function
}

It just doesn't work through the AutoIt program. I tried both 32 bit and 64 bit versions of the GUI. :dubbio:
 
Not a big deal though, I still learned quite a bit from fooling around trying to figure out why it would not work. The included calc file from your download works with my program too, but causes the program itself to crash after the calculator is thrown, even when adding a ret to clean things up at the end, so right now I am in the process of viewing the ASM from the shellcode provided in the bin file to see what might be going on there...
 
:cheers:

#13 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 07 April 2013 - 08:51 AM

I am not sure but I guess there's something wrong with your code. I generate some code in metasploit to execute notepad;

 

"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50" +
"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52" +
"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a" +
"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41" +
"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52" +
"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48" +
"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40" +
"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48" +
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41" +
"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1" +
"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c" +
"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01" +
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a" +
"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b" +
"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00" +
"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b" +
"\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd" +
"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0" +
"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff" +
"\xd5\x6e\x6f\x74\x65\x70\x61\x64\x00"

 

And it worked fine here. This was on Windows 7 x64. If notepad (the host process) crashes, that is fine as we don't need or care about that. All we want is to run the code, see if it works, and optionally enter debugging. I don't have Windows 8 at hand right now.



#14 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 07 April 2013 - 09:06 AM

But the shellcode worked directly in my compiled C binary for the one I showed you. Now what is more strange is that the code above works using your AutoIt GUI, but does not work in my C program... I'm going to have to attach the debugger to this to see why I'm getting such odd results... So far, code that has worked in my program has not worked in your GUI, and vice versa.

 

I'm assuming the shellcode did not work for you that I had though?



#15 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 07 April 2013 - 09:16 AM

Can you send a link to your program? I guess it matters what the host thread is doing.



#16 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 07 April 2013 - 09:23 AM

Sure, I'll send along with the binary, the bin file for the kernel32 Beep too. All you'll have to change is the bytes for the address...

 

Right now, it's just being interpretted directly, I plan on creating/spawning a child process to run the shellcode dynamically in the future. I have HyperV on my Win8 machine, with VM's for XP all the way up to Windows 8 itself. Including a couple Linux distro's. So fortunately for me I have the capability to test across various operating systems which comes in handy.

 

http://www.mediafire...l450cl43eu4210l



#17 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 07 April 2013 - 09:26 AM

But what does the source code of the tool look like?



#18 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 07 April 2013 - 09:29 AM

But what does the source code of the tool look like?
 
Using the method as posted above, for reading from the bin file I have this:
FILE * filePtr;
filePtr = fopen(argv[1],"r");
if (filePtr!=NULL)
{
	printf("File open succeeded, attempting to execute shellcode...\n");
	char arr[256];
	int n = 0, c = 0;
	do {
		arr[n++] = (char)(c = getc(filePtr));
	} while (c != EOF);
	fclose (filePtr);
	((void(*)())arr)();
}
else
{
	printf("Error: Could not open file...\n");
	return 1;
}
return 0;
 

Note: I increased the size of the array just to test your notepad shellcode, but it still didn't seem to work. I forgot I had a small value in there for the buffer size.

edit: Debugging my program when attempting to run the notepad.bin from your shellcode points to 0x0028D71A as the problem:
0028D716  xor         edx,edx  
0028D718  dec         eax  
0028D71A  mov         edx,dword ptr [edx+60h]
0xC0000005: Access violation reading location 0x00000060.

So after EAX gets set to 0x00000000, the dec instruction subtracts one from the destination operand being the EAX register... Reading about the dec instruction, it treats all integers as unsigned datatypes too, which makes sense, being that the instruction is to subtract from the value.

It seems like an issue with my program in this case, but what I don't get is why the beep code would run in my program, and not your AutoIt GUI?

More looking-into required I suppose...

#19 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 07 April 2013 - 10:48 AM

I don't have time to look further into it right now. Here's a good x64 tutorial; http://mcdermottcybe...s-x64-shellcode



#20 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 07 April 2013 - 10:50 AM

I don't have time to look further into it right now. Here's a good x64 tutorial; http://mcdermottcybe...s-x64-shellcode

Appreciate it joakim :) Thanks anyways. I will take a look at the link for now and do some reading. I'm assuming your test with XP SP3 was on a the x86 edition of XP and not the x64 (as the highest SP for x64 is SP2), so I guess I've got some learning of my own to do for a different archicecture.

:cheers:

#21 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 07 April 2013 - 11:30 AM

Yes OS version and arch highly matters when dealing with shellcode. The earlier test I did was on 32 bit version of XP (SP3).



#22 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 25 May 2013 - 10:06 AM

Ahh, forgot to mention I improved the ASM for the Beep shellcode I was using:
__asm
{
	mov ecx, dword ptr 0x764531AF
	xor eax, eax
	mov ax, 0x320
	push eax
	mov ax, 0x450
	push eax
	call ecx
}

Which gave me this:
\xB9\xAF\x31\x45\x76\x33\xC0\x66\xB8\x20\x03\x50\x66\xB8\x50\x04\x50\xFF\xD1\xC3​​

Removes all of the 0x0's... No need for a 32 bit storage if you only need probably 16 bits, so I split up the register in half. Thought this might help someone else reading this thread, so I'll post it.

~Ace

#23 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 18 August 2013 - 08:46 AM

I made 2 programs in C for Beep and MessageBoxA respectively, for x64. It is not possible to use the shellcode directly in ShellCodeExecGUI as the function addresses are generated at runtime from within the program. Though it demonstrates simpel shellcoding for x64. Note that inline asm is not available for x64 in visual studio, which is why it was written like this. Putting the resolving of function addresses into the shellcode would require a lot of extra code, in order to go through PEB.

 

MessageBoxA.c

#include <stdio.h>
#include <windows.h>
//only for x64
/*
//MessageBoxA without caption and text
char shellcode[] =  "\x90"       //int 3
     "\x48\x83\xEC\x28"    //sub rsp,28h
     "\x45\x33\xC9"     //xor r9d,r9d
     "\x45\x33\xC0"     //xor r8d,r8d
     "\x33\xD2"      //xor edx,edx
     "\x33\xC9"      //xor ecx,ecx
     "\xFF\x15\x07\x00\x00\x00"  //call qword ptr (+0x7)
     "\x33\xC0"      //xor eax,eax
     "\x48\x83\xC4\x28"    //add rsp,28h
     "\xC3"       //ret
     "\x00\x00\x00\x00"    //address of function generated at runtime
     "\x00\x00\x00\x00";
*/
//MessageBoxA with Caption and text
char shellcode[] = "\x90"       //int 3
     "\x48\x83\xEC\x28"    //sub rsp,28h
     "\x4C\x8D\x05\x21\x00\x00\x00" //lea r8,[string lpCaption +0x21]
     "\x48\x8D\x15\x20\x00\x00\x00" //lea rdx,[string lpText +0x20]
     "\x45\x33\xC9"     //xor r9d,r9d
     "\x33\xC9"      //xor ecx,ecx
     "\xFF\x15\x07\x00\x00\x00"  //call qword ptr (+0x7)
     "\x33\xC0"      //xor eax,eax
     "\x48\x83\xC4\x28"    //add rsp,28h
     "\xC3"       //ret
     "\x00\x00\x00\x00"    //address of function generated at runtime
     "\x00\x00\x00\x00"
     "\x50\x57\x4E\x45\x44"   //lpCaption
     "\x00"       //string terminator
     "\x48\x61\x48\x61\x21";   //lpText

int main(int argc, char **argv)
{
 unsigned char byteArray[4];
 DWORD oldProtect;
 LPVOID lpLoadAddress;
 //Load module and get address of function
 //user32.dll must be loaded before we can get address
 lpLoadAddress = GetProcAddress(LoadLibraryA("user32.dll"), "MessageBoxA");
 printf("Target address: 0x%08X\n", lpLoadAddress);
 
 //Convert the address to a byte array
 byteArray[0] = (((ULONG)lpLoadAddress >> 24) & 0xFF);
 byteArray[1] = (((ULONG)lpLoadAddress >> 16) & 0xFF);
 byteArray[2] = (((ULONG)lpLoadAddress >> 8) & 0XFF);
 byteArray[3] = (((ULONG)lpLoadAddress & 0XFF));
 //Put in the right address of function in shellcode
 shellcode[37] = byteArray[3];
 shellcode[38] = byteArray[2];
 shellcode[39] = byteArray[1];
 shellcode[40] = byteArray[0];
 //Make our memory location executable
    if (0 == VirtualProtect(&shellcode, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &oldProtect))
 {
        printf("Error in VirtualProtect: %d\n", GetLastError());
        return 0;
    }
 //Execute the code
 ((void (*)())shellcode)();
 return 1;
}

 

 

Beep.c

#include <stdio.h>
#include <windows.h>
//only for x64
//Beep
char shellcode[] = "\x90"       //int 3
     "\x48\x83\xEC\x28"    //sub rsp,28h
     "\xBA\x2C\x01\x00\x00"   //mov edx,12Ch
     "\xB9\xEE\x02\x00\x00"   //mov ecx,2EEh
     "\xFF\x15\x07\x00\x00\x00"  //call qword ptr (+0x7)
     "\x33\xC0"      //xor eax,eax
     "\x48\x83\xC4\x28"    //add rsp,28h
     "\xC3"       //ret
     "\x00\x00\x00\x00"    //address of function generated at runtime
     "\x00\x00\x00\x00";
int main(int argc, char **argv)
{
 unsigned char byteArray[4];
 DWORD oldProtect;
 LPVOID lpLoadAddress;
 //Load module and get address of function
 //kernel32.dll is always loaded so we just access the module
 lpLoadAddress = GetProcAddress(GetModuleHandleA("kernel32.dll"), "Beep");
 printf("Target address: 0x%08X\n", lpLoadAddress);
 //Convert the address to a byte array
 byteArray[0] = (((ULONG)lpLoadAddress >> 24) & 0xFF);
 byteArray[1] = (((ULONG)lpLoadAddress >> 16) & 0xFF);
 byteArray[2] = (((ULONG)lpLoadAddress >> 8) & 0XFF);
 byteArray[3] = (((ULONG)lpLoadAddress & 0XFF));
 //Put in the right address of function in shellcode
 shellcode[28] = byteArray[3];
 shellcode[29] = byteArray[2];
 shellcode[30] = byteArray[1];
 shellcode[31] = byteArray[0];
 //Make our memory location executable
    if (0 == VirtualProtect(&shellcode, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &oldProtect))
 {
        printf("Error in VirtualProtect: %d\n", GetLastError());
        return 0;
    }
 //Execute the code
 ((void (*)())shellcode)();
 return 1;
}

 

The code will only work on 64-bit.


  • AceInfinity likes this

#24 AceInfinity

AceInfinity

    Frequent Member

  • Team Reboot
  • 228 posts
  • Location:Canada
  • Interests:Windows Security, Programming, Customizing & Crash Dump Analysis.
  •  
    Canada

Posted 19 August 2013 - 01:45 AM

I looked into this a while back, and for x64, it's as trivial as raising the protection level for that page, because most kernels now mark DATA as not executable. (A byproduct policy of the DEP - Data Execution Prevention implementation as far as I'm aware.) The same principle is responsible for how programs like Google Chrome compile (and execute) Javascript to native code (WebKit nitro engine).By default for Windows I think DEP is only turned on for essential Windows programs and services.

I would be curious about ARM though... Because it specifies several instruction execution modes such as Thumb16, Thumb32, and ARM... :dubbio:

 

edit: Your return 0, and return 1 in that code should be reversed however I think. :loleverybody:

 

Nice work though :) I never changed the protection so I was able to run it directly for x86 and because DEP was off presumably.



#25 joakim

joakim

    Silver Member

  • Team Reboot
  • 912 posts
  • Location:Bergen
  •  
    Norway

Posted 19 August 2013 - 06:45 AM

Regarding ARM, I really have not much knowledge..

 

Maybe the return values should have been changed. It just was not part of the core logic, so could have removed it altogether by changing the function from int to void.

 

Regarding the first byte in the shellcode, where it in comments says "int 3". There currently is 0x90 (NOP), but can be changed to 0xCC (INT 3) to make your JIT debugger break at shellcode. Though I am rather sure you figured out that.






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users