/*
*
*
* Compile: cl /GS- /Os shellcode.c /link /fixed /release
*
*/
#define VERIFY_SHELLLCODE 1
#if VERIFY_SHELLLCODE
//
/* shellcode & test */
static unsigned char shellcode[397]={
0x55,0x8b,0xec,0x83,0xec,0x14,0x53,0x56,0x57,0xeb,0x63,0x56,0x33,0xc0,0x64,0x8b,
0x40,0x30,0x8b,0x40,0x0c,0x8b,0x70,0x1c,0xad,0x8b,0x40,0x08,0x5e,0xc3,0x60,0x8b,
0x6c,0x24,0x24,0x8b,0x45,0x3c,0x8b,0x54,0x05,0x78,0x03,0xd5,0x8b,0x4a,0x18,0x8b,
0x5a,0x20,0x03,0xdd,0xe3,0x34,0x49,0x8b,0x34,0x8b,0x03,0xf5,0x33,0xff,0x33,0xc0,
0xfc,0xac,0x84,0xc0,0x74,0x07,0xc1,0xcf,0x0d,0x03,0xf8,0xeb,0xf4,0x3b,0x7c,0x24,
0x28,0x75,0xe1,0x8b,0x5a,0x24,0x03,0xdd,0x66,0x8b,0x0c,0x4b,0x8b,0x5a,0x1c,0x03,
0xdd,0x8b,0x04,0x8b,0x03,0xc5,0x89,0x44,0x24,0x1c,0x61,0xc2,0x08,0x00,0xe8,0x98,
0xff,0xff,0xff,0x8b,0xd8,0x89,0x45,0xec,0x68,0x8e,0x4e,0x0e,0xec,0x53,0xe8,0x9b,
0xff,0xff,0xff,0x89,0x45,0xf0,0x68,0xaa,0xfc,0x0d,0x7c,0x53,0xe8,0x8d,0xff,0xff,
0xff,0x89,0x45,0xf4,0x68,0x7e,0xd8,0xe2,0x73,0x53,0xe8,0x7f,0xff,0xff,0xff,0x89,
0x45,0xf8,0x68,0x1b,0xc6,0x46,0x79,0x53,0xe8,0x71,0xff,0xff,0xff,0x89,0x45,0xfc,
0x8d,0x75,0xec,0xe8,0x05,0x00,0x00,0x00,0x5f,0x5e,0x5b,0xc9,0xc3,0x55,0x8b,0xec,
0x83,0xec,0x14,0x53,0x8d,0x45,0xfc,0x50,0x6a,0x40,0x6a,0x14,0x56,0xff,0x56,0x10,
0x8d,0x45,0xec,0x33,0xdb,0x50,0xc6,0x45,0xec,0x75,0xc6,0x45,0xed,0x73,0xc6,0x45,
0xee,0x65,0xc6,0x45,0xef,0x72,0xc6,0x45,0xf0,0x33,0xc6,0x45,0xf1,0x32,0xc6,0x45,
0xf2,0x2e,0xc6,0x45,0xf3,0x64,0xc6,0x45,0xf4,0x6c,0xc6,0x45,0xf5,0x6c,0x88,0x5d,
0xf6,0xff,0x56,0x04,0x3b,0xc3,0x75,0x08,0x53,0xff,0x56,0x0c,0x33,0xc0,0xeb,0x7a,
0x8d,0x4d,0xec,0x51,0x50,0xc6,0x45,0xec,0x4d,0xc6,0x45,0xed,0x65,0xc6,0x45,0xee,
0x73,0xc6,0x45,0xef,0x73,0xc6,0x45,0xf0,0x61,0xc6,0x45,0xf1,0x67,0xc6,0x45,0xf2,
0x65,0xc6,0x45,0xf3,0x42,0xc6,0x45,0xf4,0x6f,0xc6,0x45,0xf5,0x78,0xc6,0x45,0xf6,
0x41,0x88,0x5d,0xf7,0xff,0x56,0x08,0x3b,0xc3,0x53,0x74,0xbd,0x8d,0x4d,0xec,0x51,
0x51,0x53,0xc6,0x45,0xec,0x68,0xc6,0x45,0xed,0x65,0xc6,0x45,0xee,0x6c,0xc6,0x45,
0xef,0x6c,0xc6,0x45,0xf0,0x6f,0xc6,0x45,0xf1,0x2c,0xc6,0x45,0xf2,0x77,0xc6,0x45,
0xf3,0x6f,0xc6,0x45,0xf4,0x72,0xc6,0x45,0xf5,0x6c,0xc6,0x45,0xf6,0x64,0xc6,0x45,
0xf7,0x21,0x88,0x5d,0xf8,0xff,0xd0,0x33,0xc0,0x40,0x5b,0xc9,0xc3,
};
int __cdecl main(int argc, char* argv[]){
((void (*) (void))shellcode)();
return 1;
}
#else //VERIFY_SHELLLCODE
//
#pragma warning(disable:4102 4731 4748 4311 4312)
/* header */
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
/* kernel32 */
#define HASH_LoadLibraryA 0xec0e4e8e
#define HASH_GetProcAddress 0x7c0dfcaa
#define HASH_ExitProcess 0x73e2d87e
#define HASH_VirtualProtect 0x7946c61b
/* kernel32 */
typedef HMODULE (WINAPI *f_LoadLibraryA)(LPCSTR);
typedef FARPROC (WINAPI *f_GetProcAddress)(HMODULE, LPCSTR);
typedef VOID (WINAPI *f_ExitProcess)(UINT);
typedef BOOL (WINAPI *f_VirtualProtect)(LPVOID, SIZE_T, DWORD, PDWORD);
/* user32 */
typedef int (WINAPI * f_MessageBoxA)(HWND,LPCSTR,LPCSTR,UINT);
/* init buffer macro */
#define YY1(s,i,a) /
s[i+0]=a;
#define YY2(s,a,b) /
s[i+0]=a;s[i+1]=b;
#define YY3(s,i,a,b,c) /
s[i+0]=a;s[i+1]=b;s[i+2]=c;
#define YY4(s,i,a,b,c,d) /
s[i+0]=a;s[i+1]=b;s[i+2]=c;s[i+3]=d;
#define YY5(s,i,a,b,c,d,e) /
s[i+0]=a;s[i+1]=b;s[i+2]=c;s[i+3]=d;s[i+4]=e;
#define YY6(s,i,a,b,c,d,e,f) /
s[i+0]=a;s[i+1]=b;s[i+2]=c;s[i+3]=d;s[i+4]=e;s[i+5]=f;
/* shellcode context*/
typedef struct _SHELLCODE_CTX
{
/* some data */
/* kernel32 base*/
DWORD kernel32_base;
/* function pointers, kernel32 */
f_LoadLibraryA LoadLibraryA;
f_GetProcAddress GetProcAddress;
f_ExitProcess ExitProcess;
f_VirtualProtect VirtualProtect;
} SHELLCODE_CTX;
/* decl */
void __cdecl shellcode_start(void);
int __cdecl shellcode_main(SHELLCODE_CTX *ctx);
int __cdecl shellcode_end(void);
/* define */
static void __cdecl shellcode_start(void)
{
SHELLCODE_CTX ctx;
__asm {
jmp resolve_vmas ; Skip general functions
/*
* find_kernel32 -- PEB
*
* method : Lookup the PEB and walk one node back in the loaded
* module list. Extract the base address from this entry.
* It should point to kernel32.dll.
* targets : 95/98/ME/NT/2K/XP
* arguments: none
* return : eax (kernel32.dll base address)
* clobbers : eax
*/
find_kernel32:
push esi // Save esi
xor eax, eax
mov eax, fs:[eax+0x30] // Extract the PEB
mov eax, [eax + 0x0c] // Extract the PROCESS_MODULE_INFO pointer from the PEB
mov esi, [eax + 0x1c] // Get the address of flink in the init module list
lodsd // Load the address of blink into eax
mov eax, [eax + 0x8] // Grab the module base address from the list entry
pop esi // Restore esi
ret // Return
/*
* find_function
*
* method : Walks the export list of the given image
* until it finds a symbol whose hashed name
* matches the one that was passed in.
* targets : 95/98/ME/NT/2K/XP
* arguments: [esp + 0x24] (library base address)
* [esp + 0x28] (function hash)
* return : eax (resultant function address)
* clobbers : eax
*/
find_function:
pushad // Save all registers
mov ebp, [esp + 0x24] // Store the base address in eax
mov eax, [ebp + 0x3c] // PE header VMA
mov edx, [ebp + eax + 0x78] // Export table relative offset
add edx, ebp // Export table VMA
mov ecx, [edx + 0x18] // Number of names
mov ebx, [edx + 0x20] // Names table relative offset
add ebx, ebp // Names table VMA
find_function_loop:
jecxz find_function_finished // Jump to the end if ecx is 0
dec ecx // Decrement our names counter
mov esi, [ebx + ecx * 4] // Store the relative offset of the name
add esi, ebp // Set esi to the VMA of the current name
//compute_hash:
xor edi, edi // Zero edi
xor eax, eax // Zero eax
cld // Clear direction
compute_hash_again:
lodsb // Load the next byte from esi into al
test al, al // Test ourselves.
jz compute_hash_finished // If the ZF is set, we've hit the null term.
ror edi, 0xd // Rotate edi 13 bits to the right
add edi, eax // Add the new byte to the accumulator
jmp compute_hash_again // Next iteration
compute_hash_finished:
//find_function_compare:
cmp edi, [esp + 0x28] // Compare the computed hash with the requested hash
jnz find_function_loop // No match, try the next one.
mov ebx, [edx + 0x24] // Ordinals table relative offset
add ebx, ebp // Ordinals table VMA
mov cx, [ebx + 2 * ecx] // Extrapolate the function's ordinal
mov ebx, [edx + 0x1c] // Address table relative offset
add ebx, ebp // Address table VMA
mov eax, [ebx + 4 * ecx] // Extract the relative function offset from its ordinal
add eax, ebp // Function VMA
mov [esp + 0x1c], eax // Overwrite stack version of eax from pushad
find_function_finished:
popad // Restore all registers
ret 8 // Return
/* find kernel32.dll and some function */
resolve_vmas:
; kernel32.dll routines
call find_kernel32 ; Find kernel32 base address
mov ebx, eax ; Save the handle in ebx
mov ctx.kernel32_base,eax
push HASH_LoadLibraryA ; Push function hash
push ebx ; Push base handle
call find_function ; Find function
mov ctx.LoadLibraryA, eax ; Save the VMA
push HASH_GetProcAddress ; Here we go again..
push ebx
call find_function
mov ctx.GetProcAddress, eax
push HASH_ExitProcess
push ebx
call find_function
mov ctx.ExitProcess, eax
push HASH_VirtualProtect
push ebx
call find_function
mov ctx.VirtualProtect, eax
}
/* Now call the shellcode main function */
shellcode_main(&ctx);
}
static int __cdecl shellcode_main(SHELLCODE_CTX *ctx)
{
DWORD old_vp;
char buffer[16];
HMODULE user32_base;
f_MessageBoxA MessageBoxA;
// Our context needs to be executable and writable
ctx->VirtualProtect(ctx,sizeof(SHELLCODE_CTX),PAGE_EXECUTE_READWRITE,&old_vp);
// get MessageBoxA
YY6(buffer,0,'u','s','e','r','3','2');
YY5(buffer,6,'.','d','l','l',0);
user32_base = ctx->LoadLibraryA(buffer);
if(!user32_base){
ctx->ExitProcess(0);
return 0;
}
YY6(buffer,0,'M','e','s','s','a','g');
YY6(buffer,6,'e','B','o','x','A',0);
MessageBoxA = (f_MessageBoxA)ctx->GetProcAddress(user32_base,buffer);
if(!MessageBoxA){
ctx->ExitProcess(0);
return 0;
}
/* invoke MessageBoxA */
YY6(buffer,0,'h','e','l','l','o',',');
YY6(buffer,6,'w','o','r','l','d','!');
YY1(buffer,12,0);
MessageBoxA(0,buffer,buffer,0);
return 1;
}
static __declspec(naked) int __cdecl shellcode_end(void)
{
__asm ret
}
//
/* hash util */
static unsigned long __stdcall calc_hash(char* str)
{
unsigned long crc = 0;
while(*str){
crc = (crc >> 13) + (crc << 19);
crc+=*str;
str++;
}
return crc;
}
/* main */
int __cdecl _tmain(int argc, _TCHAR* argv[])
{
unsigned char *start, *end;
unsigned long length,index;
/* print shellcode */
start = (unsigned char *)shellcode_start;
end = (unsigned char *)shellcode_end;
length = (unsigned long)(end - start);
printf("static unsigned char shellcode[%d]={/n",length);
for (index = 0; index < length; index++)
{
printf("0x%02x,", start[index] & 0xff);
if (index % 16 == 15)
printf("/n");
}
printf("/n};/n");
/* run shellcode */
shellcode_start();
return 0;
}
#endif //VERIFY_SHELLLCODE
发表评论 取消回复