{***************
功能 获取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;
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!