理论基础:
- 假设需要弹出一个MessageBox,那么至少需要使用到以下这些API或模块:
- GetProcAddress()------>14Byte
- LoadLibraryExA()------->14Byte
- ExitProcess()------------->11Byte
- User32.dll()--------------->10Byte
- MessageBox()----------->11Byte
- 仅仅一个简单的MessageBox就有60个与逻辑无关的字节参与进来,必须进行优化
- 办法:通过算法变成一个32位的HASH摘要
算法设计:
需注意:通过HASH算法生成的摘要中尽可能的避免出现0x00与0x0A(会截断输入)
具体实现:
#include "stdafx.h" //需注意代码的长度,中间call函数的话需要特别注意是否完整了。在OD中查看 char bShellcode[] = "x83xECx20xEBx0Bx55x73x65x72x33x32x2Ex64x6Cx6Cx00xE8x00x00x00x00x5B" "xE8x31x00x00x00x50x68x87x32xD8xC0xE8x92x00x00x00x56x8BxF0x8Dx43xF0" "x6Ax00x6Ax00x50xFFxD6x50x68x6Ax0Ax38x1ExE8x7Ax00x00x00x6Ax00x6Ax00" "x6Ax00x6Ax00xFFxD0x8BxE5x5DxC3x55x8BxECx83xECx0Cx64xA1x30x00x00x00" "x8Bx40x0Cx8Bx40x0Cx8Bx00x8Bx00x3Ex8Bx40x18x8BxE5x5DxC3x55x8BxECx83" "xECx04xC7x45xFCx00x00x00x00x53x51x52x8Bx75x08x33xC9x33xC0x8Ax04x0E" "x84xC0x74x16x8Bx5DxFCxC1xE3x19x8Bx55xFCxC1xEAx07x0BxDAx03xD8x89x5D" "xFCx41xEBxE3x8Bx5Dx0Cx8Bx55xFCx33xC0x3BxDAx75x05xB8x01x00x00x00x5A" "x59x5Bx8BxE5x5DxC2x08x00x55x8BxECx83xECx0Cx52x8Bx55x0Cx8Bx72x3Cx8D" "x34x32x8Bx76x78x8Dx34x32x8Bx7Ex1Cx8Dx3Cx3Ax89x7DxFCx8Bx7Ex20x8Dx3C" "x3Ax89x7DxF8x8Bx7Ex24x8Dx3Cx3Ax89x7DxF4x33xC9xEBx01x41x8Bx75xF8x8B" "x34x8Ex8Bx55x0Cx8Dx34x32xFFx75x08x56xE8x67xFFxFFxFFx85xC0x74xE6x8B" "x75xF4x33xFFx66x8Bx3Cx4Ex8Bx55xFCx8Bx34xBAx8Bx55x0Cx8Dx04x32x5Ax8B" "xE5x5DxC2x08x00"; int main() { __asm { LEA EAX, bShellcode; PUSH EAX; RET; } return 0; }
//********************************************** //哈希摘要算法(取摘要) //参数为 函数名字符串 //返回值:哈希值 //********************************************* int Hash_GetDigest(char* strFunName) { unsigned int nDigest = 0; while (*strFunName) { //左移25位,右移7位,按位或 nDigest = ((nDigest << 25) | (nDigest >> 7)); nDigest = nDigest + *strFunName; strFunName++; } return nDigest; } int hash_Loadlibrary = Hash_GetDigest("LoadLibraryExA");//0xc0d83287 int hash_MessBox = Hash_GetDigest("MessageBoxA");//0x1e380a6a