我们直接写入可能无法执行
unsigned char data[130] = { 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x0C, 0xC7, 0x45, 0xF8, 0x00, 0x00, 0x40, 0x00, 0x8B, 0x45, 0xF8, 0x0F, 0xB7, 0x08, 0x81, 0xF9, 0x4D, 0x5A, 0x00, 0x00, 0x74, 0x04, 0x33, 0xC0, 0xEB, 0x5F, 0x8B, 0x55, 0xF8, 0x8B, 0x45, 0xF8, 0x03, 0x42, 0x3C, 0x89, 0x45, 0xFC, 0x8B, 0x4D, 0xFC, 0x81, 0x39, 0x50, 0x45, 0x00, 0x00, 0x74, 0x04, 0x33, 0xC0, 0xEB, 0x44, 0x8B, 0x55, 0xFC, 0x0F, 0xB7, 0x42, 0x18, 0x3D, 0x0B, 0x01, 0x00, 0x00, 0x74, 0x04, 0x33, 0xC0, 0xEB, 0x32, 0x8B, 0x4D, 0xFC, 0x83, 0x79, 0x74, 0x0E, 0x77, 0x04, 0x33, 0xC0, 0xEB, 0x25, 0xBA, 0x08, 0x00, 0x00, 0x00, 0x6B, 0xC2, 0x0E, 0x8B, 0x4D, 0xFC, 0x83, 0x7C, 0x01, 0x78, 0x00, 0x74, 0x09, 0xC7, 0x45, 0xF4, 0x01, 0x00, 0x00, 0x00, 0xEB, 0x07, 0xC7, 0x45, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x45, 0xF4, 0x8B, 0xE5, 0x5D, 0xC3 }; typedef void(*PFN_FOO)(); int main() { PFN_FOO f = (PFN_FOO)(void *)data; f();
无法执行
可以看到可读可写不可执行,修改保存就行了 因为shellcode在程序的全局区,没有可执行权限,代码所在内存必须可读可执行,但是重新编译不行,因为重新编译了就变了,所以还可以在当前程序申请一块可写可读可执行的代码区
VirtualAlloc
LPVOID VirtualAlloc( LPVOID lpAddress, // region to reserve or commit SIZE_T dwSize, // size of region DWORD flAllocationType, // type of allocation DWORD flProtect // type of access protection);
这里来申请一块
LPVOID lpAddr = VirtualAlloc( NULL, //表示任意地址,随机分配 1, //内存通常是以分页为单位来给空间 1页=4k 4096字节 MEM_COMMIT, //告诉操作系统给分配一块内存 PAGE_EXECUTE_READWRITE ); if (lpAddr == NULL){ printf("Alloc error!"); return 0; }
可以看到内存已经申请好了,接下来就把我们的数据拷贝过来,再执行,最后还要释放掉
memcpy(lpAddr, data, sizeof(data)); typedef void(*PFN_FOO)(); PFN_FOO f = (PFN_FOO)(void*)lpAddr; f(); VirtualFree(lpAddr,1,MEM_DECOMMIT);
完整代码
unsigned char data[130] = { 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x0C, 0xC7, 0x45, 0xF8, 0x00, 0x00, 0x40, 0x00, 0x8B, 0x45, 0xF8, 0x0F, 0xB7, 0x08, 0x81, 0xF9, 0x4D, 0x5A, 0x00, 0x00, 0x74, 0x04, 0x33, 0xC0, 0xEB, 0x5F, 0x8B, 0x55, 0xF8, 0x8B, 0x45, 0xF8, 0x03, 0x42, 0x3C, 0x89, 0x45, 0xFC, 0x8B, 0x4D, 0xFC, 0x81, 0x39, 0x50, 0x45, 0x00, 0x00, 0x74, 0x04, 0x33, 0xC0, 0xEB, 0x44, 0x8B, 0x55, 0xFC, 0x0F, 0xB7, 0x42, 0x18, 0x3D, 0x0B, 0x01, 0x00, 0x00, 0x74, 0x04, 0x33, 0xC0, 0xEB, 0x32, 0x8B, 0x4D, 0xFC, 0x83, 0x79, 0x74, 0x0E, 0x77, 0x04, 0x33, 0xC0, 0xEB, 0x25, 0xBA, 0x08, 0x00, 0x00, 0x00, 0x6B, 0xC2, 0x0E, 0x8B, 0x4D, 0xFC, 0x83, 0x7C, 0x01, 0x78, 0x00, 0x74, 0x09, 0xC7, 0x45, 0xF4, 0x01, 0x00, 0x00, 0x00, 0xEB, 0x07, 0xC7, 0x45, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x45, 0xF4, 0x8B, 0xE5, 0x5D, 0xC3 }; int main() { LPVOID lpAddr = VirtualAlloc( NULL, //表示任意地址,随机分配 1, //内存通常是以分页为单位来给空间 1页=4k 4096字节 MEM_COMMIT, //告诉操作系统给分配一块内存 PAGE_EXECUTE_READWRITE ); if (lpAddr == NULL){ printf("Alloc error!"); return 0; } //到这里表示能够成功分配内存 memcpy(lpAddr, data, sizeof(data)); typedef void(*PFN_FOO)(); PFN_FOO f = (PFN_FOO)(void*)lpAddr; f(); VirtualFree(lpAddr,1,MEM_DECOMMIT); return 0;
这里我们本地写个messagebox,可以看到helloworld是再常量区地址为0C65858h,但是函数的引用地址却在0C6916Ch,他们之间是有强烈的依赖关系,所以我们如果直接把代码抽出来是无法利用的
所以如果上面我们想要执行成功就要处理掉相关依赖,比如相关函数的地址,字符串地址 自己重定位了,shellcode:一段与地址无关的代码,只要把它放在任意32位程序中只要给他一个起点就能执行 所以我们要先开辟空间然后再写入,然是可以看到VirtualAlloc写了谁调用在谁哪里开辟空间
所以我们就用加强版VirtualAllocEx,它可以在指定进程去开辟 VirtualAllocEx
代码差不多,但是这里我们要先获取我们要注入的进程句柄,这里shellcode为32位所以我们需要获取的也是32位的
就是昨天的代码,然后再来开辟一个空间
然后我们就是要写入,这里就不能使用memcpy了因为这个是当前进程调用的 WriteProcessMemory
这里我们就写入进去
写进去了还要调用才能执行,创建远程线程 CreateRemoteThread
返回目标进程的线程
这里我们不要立马释放因为可能执行需要一段时间,所以要等待执行完毕再释放 完成代码为
点赞 转发 在看
原创投稿作者:一寸一叶
本文作者:HACK_Learn
本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/145415.html