windows平台shellcode

Windows平台 shellcode 制作方法

看了FreeBuf上面关于ShellCode编写方法,总结一下

工程设置

  1. 使用Release版本编译
  2. 代码生成->运行库 选择 多线程(/MT)
  3. 代码生成->安全检查 禁用
  4. 清单文件->生成清单
  5. 调试->生成调试信息
  6. 高级->入口点 自定义的入口函数
  7. 优化 关闭
  8. 平台工具集 支持到xp

代码原则

  1. 双引号字符串
1
2
char szData[] = {'1','2','3','4','5','\0'};// 正确
memcpy(szData,"12345");// 错误

或者内嵌汇编

1
2
3
4
5
6
7
8
9
10
11
12
13
char *pszData;
__asm{
call _pszData
_EMIT '1'
_EMIT '2'
_EMIT '3'
_EMIT '4'
_EMIT '5'
_EMIT '6'
_EMIT 0
_pszData:
pop pszData
}

  1. 函数动态调用

不能直接使用windowsAPI,通过GetProcAddress动态获得函数地址
可以选择汇编调用

1
2
3
4
5
6
7
8
LPVOID lp = GetProcAddress(LoadLibraryA("user32.dll"),"MessageBoxA");
__asm{
push 0
push 0
push 0
push 0
call lp
}

或者可以:先声明函数,动态获得函数地址,最后再调用

1
2
3
4
5
6
7
8
9
10
11
12
typedef HANDLE (WINAPI* FN_CreateFileA)(
__in LPCSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_out LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_out HANDLE hTemplateFile
);
FN_CreateFileA fn_CreateFileA;
fn_CreateFileA = (FN_CreateFileA)GetProcAddress(LoadLibraryA("kernel32.dll"), "CreateFileA");
fn_CreateFileA("hello.txt",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);

  1. 获得LoadLibraryA的地址和获取kernel32基址

参考1
参考2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
__declspec(naked) DWORD getLoadLibraryA(){
__asm{
mov eax, fs:[30h]
mov eax, [eax+0ch]
mov eax, [eax+14h]
mov eax, [eax]
mov eax, [eax]
mov eax, [eax+10h]
ret
}
}
int main(){
HMODULE hLoadLibraryA = (HMODULE)getLoadLibraryA();
}

获得GetProcAddress的地址
视频里的操作太秀了,跟不上,有机会再补充上吧

  1. 避免全局变量的使用

在全局定义,在函数中使用是不可以的
因为全局变量被编译时放在单独段中,在使用时会导致绝对地址的引用

  1. 确保已加载所使用的API所在的动态链接库

在调用API时,应先使用LoadLibraryA这个函数加载函数所在的动态链接库到内存中

shellcode加载器

1
2
3
4
5
6
7
8
9
HANDLE hFile = CreateFileA(argv[1],GENERIC_READ,0,NULL,OPEN_ALWAYS,0,NULL);
DWORD dwSzie;
dwSize = GetFileSize(hFile,NULL);
LPVOID lpAddress = VirtualAlloc(NULL,dwSize,MEN_COMMIT,PAGE_EXECUTE_READWRITE);
DWORD dwRead;
ReadFile(hFile,lpAddress,dwSzie,&dwRead,0);
__asm{
call lpAddress;
}

完整代码等我有空的时候再添加上吧