什么是ShellCode?

不依赖环境,放到任何地方都可以执行的机器码

shellcode编写原则

  1. 不能有全局变量
  2. 不能使用常量字符串
  3. 不能使用系统调用
  4. 不能嵌套调用其他函数

案例思路

通过TEB结构体查找PEB,然后在PEB中找到_PEB_LDR_DATA,再从_PEB_LDR_DATA中找到InLoadOrderModuleList,这是一个链表,链表内存储的是有关所有加载dll的相关信息,可以通过这个结构来进行断链dll隐藏,_LDR_DATA_TABLE_ENTRY这是链表里的node的结构体,接下来我们遍历我们想要找到的dll,拿到DllBase,之后通过PE的知识解析,从中找到导出表,从导出表中拿到GetProcAddressLoadLibraryA函数,之后就可以通过这两个函数进行加载dll和使用dll中的函数。

其中有关_LDR_DATA_TABLE_ENTRY结构体内容如下,可以参考看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//0x50 bytes (sizeof)
struct _LDR_DATA_TABLE_ENTRY
{
struct _LIST_ENTRY InLoadOrderLinks; //0x0
struct _LIST_ENTRY InMemoryOrderLinks; //0x8
struct _LIST_ENTRY InInitializationOrderLinks; //0x10
VOID* DllBase; //0x18
VOID* EntryPoint; //0x1c
ULONG SizeOfImage; //0x20
struct _UNICODE_STRING FullDllName; //0x24
struct _UNICODE_STRING BaseDllName; //0x2c
ULONG Flags; //0x34
USHORT LoadCount; //0x38
USHORT TlsIndex; //0x3a
union
{
struct _LIST_ENTRY HashLinks; //0x3c
struct
{
VOID* SectionPointer; //0x3c
ULONG CheckSum; //0x40
};
};
union
{
ULONG TimeDateStamp; //0x44
VOID* LoadedImports; //0x44
};
VOID* EntryPointActivationContext; //0x48
VOID* PatchInformation; //0x4c
};

实例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// demo08shellcode.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
//function
typedef FARPROC (WINAPI *GETPROCADDRESS)(HMODULE hModule,LPCSTR lpProcName);
typedef int (WINAPI *MESSAGEBOXA)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
typedef HMODULE (WINAPI *LOADLIBRARYA)(LPCSTR lpLibFileName);

GETPROCADDRESS PGETPROCADDRESS;
MESSAGEBOXA PMESSAGEBOX;
LOADLIBRARYA PLOADLIBRARY;

//struct
typedef struct _UNICODE_STRING
{
USHORT Length; //0x0
USHORT MaximumLength; //0x2
PWSTR Buffer; //0x4
}UNICODE_STRING;
//0x0 bytes (sizeof)
//0x28 bytes (sizeof)
typedef struct _PEB_LDR_DATA
{
DWORD Length; //0x0
BYTE Initialized; //0x4
VOID* SsHandle; //0x8
LIST_ENTRY InLoadOrderModuleList; //0xc
LIST_ENTRY InMemoryOrderModuleList; //0x14
LIST_ENTRY InInitializationOrderModuleList; //0x1c
VOID* EntryInProgress; //0x24
}PEB_LDR_DATA;

typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks; //0x0
LIST_ENTRY InMemoryOrderLinks; //0x8
LIST_ENTRY InInitializationOrderLinks; //0x10
VOID* DllBase; //0x18
VOID* EntryPoint; //0x1c
DWORD SizeOfImage; //0x20
UNICODE_STRING FullDllName; //0x24
UNICODE_STRING BaseDllName; //0x2c
DWORD Flags; //0x34
WORD LoadCount; //0x38
WORD TlsIndex; //0x3a
union
{
LIST_ENTRY HashLinks; //0x3c
struct
{
VOID* SectionPointer; //0x3c
DWORD CheckSum; //0x40
};
};
union
{
DWORD TimeDateStamp; //0x44
VOID* LoadedImports; //0x44
};
VOID* EntryPointActivationContext; //0x48
VOID* PatchInformation; //0x4c
}LDR_DATA_TABLE_ENTRY;

int strcmp(char* buf1,char* buf2){
while(*buf1 && *buf2 && *buf1 == *buf2){
buf1++;
buf2++;
}
if (*buf1 == *buf2)
{
return 1;
}
return 0;
}


void ToShellcode(){
LDR_DATA_TABLE_ENTRY *pPLD = NULL,*pBeg = NULL;
PGETPROCADDRESS = NULL;
PLOADLIBRARY = NULL;
PMESSAGEBOX = NULL;
WORD *pFirst = NULL,*pLast = NULL;
DWORD ret = 0,i=0;
DWORD dwKernelBase = 0;
char szKerner32[] = {'k',0,'e',0,'r',0,'n',0,'e',0,'l',0,'3',0,'2',0,'.',0,'d',0,'l',0,'l',0,0,0};
char szUser32[] = {'U','S','E','R','3','2','.','d','l','l',0};

char szGetProAddress[] = {'G','e','t','P','r','o','c','A','d','d','r','e','s','s',0};
char szLoadLibrary[] = {'L','o','a','d','L','i','b','r','a','r','y','A',0};
char szMessageBox[] = {'M','e','s','s','a','g','e','B','o','x','A',0};
char lpText[] = {0xD7,0xA2,0xC8,0xEB,0xB3,0xC9,0xB9,0xA6,0x00};
char lpCaption[]= {'s','h','e','l','l','c','o','d','e','T','e','s','t',0};

__asm{
mov eax,fs:[0x30] //PEB
mov eax,[eax+0xc] //PEB->Ldr
add eax,0x0c //LDR_DATA_TABLE_ENTRY InLoadOrderModuleList
mov pBeg,eax
mov eax,[eax]
mov pPLD,eax
}
/*
if (strcmp(szMessageBox,name))
{
printf("%d:--%s--%x\n",t+1,name,funAddress);
PMESSAGEBOX = (MESSAGEBOX)funAddress;
}*/
//kernel32.dll
while (pPLD != pBeg)
{
pLast = (WORD*)pPLD->BaseDllName.Buffer;
pFirst = (WORD*)szKerner32;
while(!pLast && *pLast == *pFirst){
pLast++;
pFirst++;
}
if (*pLast == *pFirst)
{
dwKernelBase = (DWORD)pPLD->DllBase;
break;
}

pPLD = (LDR_DATA_TABLE_ENTRY*)pPLD->InLoadOrderLinks.Flink;
}

PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)dwKernelBase;
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
PIMAGE_FILE_HEADER pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
DWORD dataDirectorySize = sizeof(pOptionHeader->DataDirectory) / sizeof(IMAGE_DATA_DIRECTORY);
PIMAGE_DATA_DIRECTORY pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory;
PIMAGE_EXPORT_DIRECTORY pExportTable = (PIMAGE_EXPORT_DIRECTORY)(dwKernelBase + pDataDirectory->VirtualAddress);
LPVOID funNameBase = (LPVOID)(dwKernelBase + pExportTable->AddressOfNames);
LPVOID funAddressBase = (LPVOID)(dwKernelBase + pExportTable->AddressOfFunctions);

for (DWORD t = 0;t<pExportTable->NumberOfNames;t++)
{
DWORD funAddress = dwKernelBase + *(PDWORD)((DWORD)funAddressBase+(t*4));
char* name = (char*)(dwKernelBase + *(PDWORD)((DWORD)funNameBase+(t*4)));
//printf("name:%s\n",name);

if (strcmp(szGetProAddress,name))
{
printf("%d:--%s--%x\n",t+1,name,funAddress);
PGETPROCADDRESS = (GETPROCADDRESS)funAddress;
}else if (strcmp(szLoadLibrary,name))
{
printf("%d:--%s--%x\n",t+1,name,funAddress);
PLOADLIBRARY = (LOADLIBRARYA)funAddress;
}
}
//getchar();
HMODULE hmodule = PLOADLIBRARY((LPCSTR)szUser32);
PMESSAGEBOX = (MESSAGEBOXA)PGETPROCADDRESS(hmodule,szMessageBox);
PMESSAGEBOX(0,lpText,lpCaption,MB_OK);
return;
}


int main(int argc, char* argv[])
{
ToShellcode();

printf("Hello World!\n");
return 0;
}

本站由 RuntimeBroker 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本"页面"访问 次 | 👀总访问 次 | 总访客