{*************** 功能 获取kernel32.dll 的模块基地址 返回 k32基址 作者 饿狼传说 (lofullen) ***************} FUNCTION GetKernel32Module(): Cardinal; assembler asm push esi mov eax, fs:$30 mov eax, [eax+$0c] mov esi, [eax+$1c] lodsd mov eax, [eax+$08] pop esi end; {*************** 功能 计算字符串的长度 参数 eax = 字符串首指针 返回 长度 作者 饿狼传说 (lofullen) ***************} FUNCTION LStrLengthA(const lpStr: PAnsiChar): Cardinal; assembler; asm push edi push ebx mov edi, eax mov ebx, eax xor al, al // al = 00 遇到字符串末尾则退出循环 mov cx, 255 // cx = ff 字符串超过255则退出循环 repne scasb dec edi sub edi, ebx mov eax, edi pop ebx pop edi end; {*************** 功能 计算短字符串精确CRC32 参数 eax = 字符串首指针 返回 crc32 作者 饿狼传说 (lofullen) ***************} FUNCTION CalcBufferCRC(lpBuffer:PAnsiChar): Cardinal; assembler; var checksum : DWORD; asm push ebx push ecx push edx push edi push esi mov ebx, eax call LStrLengthA // eax = 字符串长度 xor edx, edx // edx = 整除后的余数 mov ecx, 4 div ecx xor ecx, ecx @@loopBegin: dec eax // eax = 整除后的整数 jl @@loopOver xor ecx, dword ptr ds:[ebx] // ecx = CRC32 add ebx, 4 jmp @@loopBegin @@loopOver: test edx, edx // 如果有余数则执行 je @@Nochecksum mov eax, ecx mov esi, ebx // esi = 剩余字节的首指针 lea edi, checksum mov dword ptr ds:[edi], 0 // checksum 归零 这样的做法为了保证只读取 00 之前的剩余字节 mov ecx, edx rep movsb // checksum 得到剩余字节(自然是小于4咯) lea edi, checksum xor eax, dword ptr ds:[edi] // 最后一次计算 jmp @@calcEnd @@Nochecksum: mov eax, ecx // 直接获取 ECX 中的 CRC32 @@calcEnd: pop esi pop edi pop edx pop ecx pop ebx end; {*************** 功能 计算API输出函数地址 参数 eax = 模块基地址 参数 edx = 函数 CRC32 返回 函数指针 作者 饿狼传说 (lofullen) ***************} function GetProcAddressA(hModule:Cardinal; dwExportCRC: Cardinal) : Pointer; assembler; var lpProcNameCRC, dwProcNumber: Cardinal; pProcAddress, pProcNameAddress, pProcIndexAddress: Pointer; asm push ebx push esi mov lpProcNameCRC, edx // edx=函数名CRC32 mov ebx, eax // ebx=基址 mov eax, [ebx+$3c] // eax=文件头偏移 mov esi, [ebx+eax+$78] // esi=输出表偏移,文件头+可选头的长度=$78 lea esi, [ebx+esi+$18] // esi=函数名数量 = 函数数量 [ebx+esi+$14] lodsd mov dwProcNumber, eax // eax=函数名数量 lodsd mov pProcAddress, eax // eax=函数偏移量 lodsd mov pProcNameAddress, eax // eax=函数名偏移量 lodsd mov pProcIndexAddress, eax // eax=序列号偏移量 mov edx, dwProcNumber // edx=遍历次数 @@LoopBegin: xor eax, eax // Result = 0 dec edx jl @@LoopEnd mov eax, pProcNameAddress add eax, ebx // eax=函数名基地址 mov eax, dword ptr ds:[eax+edx*4] add eax, ebx // eax=遍历函数名 call CalcBufferCRC cmp eax, lpProcNameCRC // 对比HASH jnz @@LoopBegin shl edx, 1 add edx, pProcIndexAddress // 函数基序列 movzx eax, word ptr ss:[edx+ebx] shl eax, 2 add eax, pProcAddress // 函数基地址 mov eax, [eax+ebx] add eax, ebx // Result = 函数地址 @@LoopEnd: pop esi pop ebx end; // 功能 数值转字符 // 配合 IntToStrA IntToHexA 不可单独使用 // delphi system.pas procedure CvtInt; asm OR CL,CL JNZ @CvtLoop @C1: OR EAX,EAX JNS @C2 NEG EAX CALL @C2 MOV AL,'-' INC ECX DEC ESI MOV [ESI],AL RET @C2: MOV ECX,10 @CvtLoop: PUSH EDX PUSH ESI @D1: XOR EDX,EDX DIV ECX DEC ESI ADD DL,'0' CMP DL,'0'+10 JB @D2 ADD DL,('A'-'0')-10 @D2: MOV [ESI],DL OR EAX,EAX JNE @D1 POP ECX POP EDX SUB ECX,ESI SUB EDX,ECX JBE @D5 ADD ECX,EDX MOV AL,'0' SUB ESI,EDX JMP @z @zloop: MOV [ESI+EDX],AL @z: DEC EDX JNZ @zloop MOV [ESI],AL @D5: end; // 功能 数字型转成 10进制 字符串型(pchar版) // 参数 EAX = 10进制数字 // 参数 EDX = 指向字符串(array[0..100] of char)指针 // 返回 有效字符串长度 //作者 饿狼传说 (lofullen) function IntToStrA(Value: Integer; lpBuffer: Pchar): Cardinal; assembler; asm PUSH ESI MOV ESI, ESP SUB ESP, 16 PUSH EDI MOV EDI, ECX XOR ECX, ECX // base: 0 for signed decimal PUSH EDX // result ptr XOR EDX, EDX // zero filled field width: 0 for no leading zeros CALL CvtInt MOV EAX, ECX REP MOVSB POP EDI ADD ESP, 16 POP ESI end; // 功能 数字型转成 16进制 字符串型(pchar版) // 参数 EAX = 10进制数字 // 参数 EDX = 16进制字符串格式长度 // 参数 ECX = 指向字符串(array[0..100] of char)指针 // 返回 有效字符串长度 //作者 饿狼传说 (lofullen) function IntToHexA(Value: Integer; Digits: Integer; lpBuffer: Pchar): Cardinal; assembler; asm CMP EDX, 32 // Digits < buffer length? JBE @A1 XOR EDX, EDX @A1: PUSH ESI MOV ESI, ESP SUB ESP, 32 PUSH EDI MOV EDI, ECX MOV ECX, 16 // base 16 EDX = Digits = field width CALL CvtInt MOV EAX, ECX REP MOVSB POP EDI ADD ESP, 32 POP ESI end; {*************** 功能 移位 * 10 配合 HexToIntA 不能单独使用 作者 饿狼传说 (lofullen) ***************} procedure MoveBit; asm push ebp mov ebp, esi sub ebp, edx @@loop: dec ebp jl @@end shl ecx, 4 jmp @@loop @@end: pop ebp end; {*************** 功能 16进制字符转换成10进制数值 参数 eax = 16进制字符串 返回 10进制整型 作者 饿狼传说 (lofullen) ***************} function HexToIntA(lpToken : Pchar): Cardinal; asm push ebx push ecx push edx push edi push esi mov ebx, eax //ebx = hex call LStrLengthA mov edx, eax //edx = hex bit mov esi, eax sub esi, 1 //esi = low bit xor edi, edi @@Machine: dec edx jl @@IntoOver mov al, byte ptr ds:[ebx+edx] @@step1: //0~9 cmp al, '0' jl @@IntoOver cmp al, '9' jg @@step2 sub al, 48 movzx ecx, al call MoveBit add edi, ecx jmp @@Machine @@step2: //A-F cmp al, 'A' jl @@IntoOver cmp al, 'F' jg @@step3 sub al, 65 add al, 10 movzx ecx, al call MoveBit add edi, ecx jmp @@Machine @@step3: //a-f cmp al, 'a' jl @@IntoOver cmp al, 'f' jg @@IntoOver sub al, 97 add al, 10 movzx ecx, al call MoveBit add edi, ecx jmp @@Machine @@IntoOver: mov eax, edi pop esi pop edi pop edx pop ecx pop ebx end; var RandSeed : int64; // 随机数因子 //功能 通过查询 CPU 或者 运行时钟获取随机数因子 //作者 饿狼传说 (lofullen) procedure Randomize; var Counter: Int64; asm push edx lea eax, Counter push eax call QueryPerformanceCounter mov eax, DWORD PTR SS:[Counter] test eax, eax je @@TickCount mov RandSeed, eax jmp @@Exit @@TickCount: call GetTickCount mov RandSeed, eax @@Exit: pop edx end; // 功能 根据随机数因子进行返回内的运算 // 参数 EAX = 最大值 (0~n) // 返回 随机数 // 作者 饿狼传说 (lofullen) function Random(const ARange: Integer): Integer; asm PUSH EBX MOV EBX, RandSeed // 某些主动防御对以下3条命令进行特征检查 IMUL EDX, EBX, $08088405 // 如果配合在网络端口上进行随机, 会被报木马 INC EDX MOV RandSeed, EDX MUL EDX MOV EAX, EDX POP EBX end; // 功能 通过随机的上下限来获得一个受控随机数 // 参数 eax = 随机下限 // 参数 edx = 随机上限 // 返回 eax >= n <= edx // 作者 饿狼传说 (lofullen) function GetRandomSeries(const fRadix, fFactor : Integer): Int64; asm push ebx mov ebx, eax sub edx, eax call Randomize mov eax, edx call Random add eax, ebx pop ebx end;
本贴将不断更新函数, 并修复原有函数的BUG, 学习DELPHI内联汇编的朋友也可以更贴.