用CRC保护程序(DELPHI)

用CRC保护程序(DELPHI)
2010年06月07日
  为程序加CRC校验,代码是DELPHI的
  unit AsmPatch;
  interface
  uses
  Windows, SysUtils, Classes, PEStruct;
  type
  { 文件处理参数 }
  TBakPath = (bpWindowsDir, bpSystemDir, bpWorkDir, bpTempDir);
  TDlgIcon = (diNone, diStop, diInformationx, diWarning);
  TCanRepairAct = (crAutoRepair, crInfoOk, crQuestionYesNo
  , crQuestionYesNoCancel);
  TCannotRepairAct = (cnQuit, cnInfoOkContinue, cnInfoOkQuit, cnQuestionYesNo);
  TCrcErrorAct = (ceQuit, ceInfoOkContinue, ceInfoOkQuit, ceQuestionYesNo);
  TRepairSuccAct = (rsQuit, rsExcute, rsInfoOkExcute, rsInfoOkQuit);
  TRepairFailAct = (rfQuit, rfInfoOkQuit);
  TDlgParam = record
  Text: string;
  Caption: string;
  Icon: TDlgIcon;
  end;
  PPatchParam = ^TPatchParam;
  TPatchParam = record
  FileName: WideString;
  BackupOrgFile: Boolean;
  AllowRegQuery: Boolean;
  RegKey: HKEY;
  RegSubKey: string;
  RegValue: string;
  AllowRepair: Boolean;
  BakPath: TBakPath;
  BakSubDir: string;
  BakName: string;
  CanRepair: TCanRepairAct;
  CanRepairDlg: TDlgParam;
  RepairSucc: TRepairSuccAct;
  RepairSuccDlg: TDlgParam;
  RepairFail: TRepairFailAct;
  RepairFailDlg: TDlgParam;
  CannotRepair: TCannotRepairAct;
  CannotRepairDlg: TDlgParam;
  CrcError: TCrcErrorAct;
  CrcErrorDlg: TDlgParam;
  end;
  { 文件处理结果 }
  TPatchResult = (prSuccess, prAlreadyPatched, prOpenError, prWriteError
  , prFileFormatError, prOtherError);
  PPatchInfo = ^TPatchInfo;
  TPatchInfo = record
  FileName: string;
  BakFileName: string;
  OrgSize: Cardinal;
  NewSize: Cardinal;
  AddSize: Cardinal;
  Result: TPatchResult;
  end;
  const
  MB_NONE = 0;
  ctDlgIcon: array[TDlgIcon] of DWORD =
  (MB_NONE, MB_ICONSTOP, MB_ICONINFORMATION, MB_ICONWARNING);
  ctCanRepair: array[TCanRepairAct] of DWORD =
  (MB_NONE, MB_OK, MB_YESNO, MB_YESNOCANCEL);
  ctCannotRepair: array[TCannotRepairAct] of DWORD =
  (MB_NONE, MB_OK, MB_OK, MB_YESNO);
  ctCrcError: array[TCrcErrorAct] of DWORD =
  (MB_NONE, MB_OK, MB_OK, MB_YESNO);
  ctRepairSucc: array[TRepairSuccAct] of DWORD =
  (MB_NONE, MB_NONE, MB_OK, MB_OK);
  ctRepairFail: array[TRepairFailAct] of DWORD =
  (MB_NONE, MB_OK);
  function FilePatch(Param: TPatchParam): TPatchInfo;
  implementation
  //..uses
  // PEStruct;
  //{$R ResTool.RES}
  const
  MAX_PATH = $400;
  csSectionChar = $0E0000020; //节属性代码(可执行、可读、可写)
  csSectionName = 'CODE';
  csFileFlag = 'CRC64';
  csBakExt = '.bak';
  csSizeOfExeExt = 4; //EXE文件扩展名长度
  csFileFlagLen = 16;
  csToolDataOffset = $A00; //修复工具中数据块位置
  { 附加到原PE文件尾的数据结构 }
  type
  TDataOffset = type DWORD; //内部数据偏移
  TDlgData = packed record
  Text: TDataOffset;
  Caption: TDataOffset;
  uType: DWORD;
  end;
  PAddData = ^TAddData;
  TAddData = packed record
  Flag: array[0..csFileFlagLen - 1] of Char; //文件标志
  Xor1: DWORD; //数据加密
  Pos1: TDataOffset;
  Len1: DWORD;
  Xor2: DWORD;
  Pos2: TDataOffset;
  Len2: DWORD;
  OEP: DWORD; //原代码入口
  CRCAddr: DWORD; //CRC存放地址
  CRC: DWORD; //原始CRC
  FileSize: DWORD; //原文件长度
  iAddress: DWORD; //原Import表
  AllowRegQuery: Boolean; //允许查询注册表
  RegKey: HKEY; //主键
  RegSubKey: TDataOffset; //子键
  RegValue: TDataOffset; //值(DWORD)非0不进行校验
  AllowRepair: Boolean; //允许修复
  BakPath: TBakPath; //备份文件主路径
  BakSubDir: TDataOffset; //备份文件子路径
  BakName: TDataOffset; //备份文件名
  RepairCode: TDataOffset; //用于修复的代码
  RepairCodeSize: DWORD; //代码长度
  CanRepair: TCanRepairAct; //可以修复
  CanRepairDlg: TDlgData;
  CannotRepair: TCannotRepairAct; //不能修复
  CannotRepairDlg: TDlgData;
  CrcError: TCrcErrorAct; //Crc32校验错(不允许修复)
  CrcErrorDlg: TDlgData;
  end;
  { 修复工具内部数据结构 }
  const
  csMaxDlgCaptionLen = 31;
  csMaxDlgTextLen = 127;
  type
  PToolDlgData = ^TToolDlgData;
  TToolDlgData = packed record
  Text: array[0..csMaxDlgTextLen] of Char;
  Caption: array[0..csMaxDlgCaptionLen] of Char;
  uType: DWORD;
  end;
  PToolData = ^TToolData;
  TToolData = packed record
  RepairSucc: TRepairSuccAct; //修复成功
  RepairSuccDlg: TToolDlgData;
  RepairFail: TRepairFailAct; //修复失败
  RepairFailDlg: TToolDlgData;
  end;
  const
  SizeOfTAddData = SizeOf(TAddData); //附加数据长度
  var
  ResStream: TResourceStream; //文件修复工具(资源中)
  AsmAdd_Addr: DWORD;
  Fake_tbl_Addr: DWORD;
  Fake_tbl_End: DWORD;
  Repair_Addr: DWORD;
  Repair_End: DWORD;
  type
  TCRC32Table = array[0..255] of DWORD;
  var
  CRC32Table: TCRC32Table;
  procedure Make_CRC32Table;
  asm
  PUSH EBX
  MOV EDX, OFFSET CRC32Table
  XOR EBX, EBX
  @MakeCRC32Loop:
  CMP EBX, $100
  JE @MakeCRC32_Succ
  MOV EAX, EBX
  MOV ECX, 8
  @MakeLoop:
  TEST EAX, 1
  JZ @MakeIsZero
  SHR EAX, 1
  XOR EAX, $EDB88320
  JMP @MakeNext
  @MakeIsZero:
  SHR EAX, 1
  @MakeNext:
  LOOP @MakeLoop
  MOV DWORD PTR [EDX], EAX
  ADD EDX, 4
  INC EBX
  JMP @MakeCRC32Loop
  @MakeCRC32_Succ:
  POP EBX
  RET
  end;
  function CRC32Calc(CRC: DWORD; Data: Pointer; DataLen: DWORD): DWORD;
  asm
  OR EDX, EDX //Data = nil?
  JE @Exit
  JECXZ @Exit //DataLen = 0?
  PUSH ESI
  PUSH EBX
  MOV ESI, OFFSET CRC32Table
  @Upd:
  MOVZX EBX, AL //CRC32
  XOR BL, [EDX]
  SHR EAX, 8
  AND EAX, $00FFFFFF
  XOR EAX, [EBX + ESI]
  INC EDX
  LOOP @Upd
  POP EBX
  POP ESI
  @Exit:
  RET
  end;
  //-----------------------------------------------//
  //附加到PE文件尾的代码(起始) //
  //-----------------------------------------------//
  //主代码
  procedure AsmAdd;
  asm
  MOV EAX, OFFSET @Start
  MOV AsmAdd_Addr, EAX
  MOV EAX, OFFSET @Fake_tbl
  MOV Fake_tbl_Addr, EAX
  MOV EAX, OFFSET @Fake_tbl_End
  MOV Fake_tbl_End, EAX
  MOV EAX, OFFSET @Repair_Code_Start
  MOV Repair_Addr, EAX
  MOV EAX, OFFSET @Repair_Code_End
  MOV Repair_End, EAX
  RET
  @Start: { 代码入口 }
  PUSHAD
  CALL @Delta
  @Delta:
  POP EBP //得到实际EIP
  SUB EBP, OFFSET @Delta //计算地址偏移修正
  LEA EDI, [EBP + @Start]
  SUB EDI, SizeOfTAddData //附加数据地址
  MOV DWORD PTR [EBP + @AddData], EDI
  MOV ECX, [EDI].TAddData.Len1
  MOV ESI, EDI
  ADD ESI, [EDI].TAddData.Pos1
  MOV EAX, [EDI].TAddData.Xor1
  CALL @DataDecode
  MOV ECX, [EDI].TAddData.Len2
  MOV ESI, EDI
  ADD ESI, [EDI].TAddData.Pos2
  MOV EAX, [EDI].TAddData.Xor2
  CALL @DataDecode
  PUSH 0
  CALL DWORD PTR [EBP + @_GetModuleHandle] //获得应用程序模块句柄
  MOV DWORD PTR [EBP + @hInstance], EAX
  CALL @QueryReg //查询注册表
  JC @JmpToOrgCode
  //-----------------------------------------------//
  //CRC32校验(准备工作) //
  //-----------------------------------------------//
  @DoCRC32Calc:
  CALL @MakeCRC32Table //初始化CRC32校验表
  JC @Quit
  MOV EDI, DWORD PTR [EBP + @AddData] //处理参数
  @GetFileName: { 应用程序名 }
  PUSH MAX_PATH
  PUSH LMEM_FIXED
  CALL DWORD PTR [EBP + @_LocalAlloc] //分配临时内存保存文件名
  OR EAX, EAX
  JZ @Quit
  MOV DWORD PTR [EBP + @lpFileName], EAX
  PUSH MAX_PATH
  MOV EBX, DWORD PTR [EBP + @lpFileName]
  PUSH EBX
  MOV EBX, DWORD PTR [EBP + @hInstance]
  PUSH EBX
  CALL DWORD PTR [EBP + @_GetModuleFileName] //获得应用程序名
  OR EAX, EAX
  JZ @QUIT
  MOV AL, [EDI].TAddData.AllowRepair //允许修复?
  OR AL, AL
  JZ @OpenFile
  Call @PrepairBackup //准备备份文件名等
  JC @Quit
  //-----------------------------------------------//
  //CRC32校验 //
  //-----------------------------------------------//
  @OpenFile: { 打开并映射应用程序文件 }
  PUSH 0
  PUSH FILE_ATTRIBUTE_NORMAL
  PUSH OPEN_EXISTING
  PUSH 0
  PUSH FILE_SHARE_READ
  PUSH GENERIC_READ
  MOV EAX, DWORD PTR [EBP + @lpFileName]
  PUSH EAX
  CALL DWORD PTR [EBP + @_CreateFile] //打开文件
  CMP EAX, INVALID_HANDLE_VALUE
  JZ @Quit
  MOV DWORD PTR [EBP + @hFile], EAX //文件句柄
  PUSH 0
  PUSH 0
  PUSH 0
  PUSH PAGE_READONLY
  PUSH 0
  PUSH EAX
  CALL DWORD PTR [EBP + @_CreateFileMapping] //创建映射文件
  OR EAX, EAX
  JZ @Quit
  MOV DWORD PTR [EBP + @hFileMap], EAX //映射文件句柄
  PUSH 0
  PUSH 0
  PUSH 0
  PUSH FILE_MAP_READ
  PUSH EAX
  CALL DWORD PTR [EBP + @_MapViewOfFile] //映射文件到内存
  OR EAX, EAX
  JZ @Quit
  MOV DWORD PTR [EBP + @lpFileMapping], EAX //内存指针
  PUSH FILE_END
  PUSH 0
  PUSH 0
  MOV EAX, DWORD PTR [EBP + @hFile]
  PUSH EAX
  CALL DWORD PTR [EBP + @_SetFilePointer] //设置文件指针
  CMP EAX, -1
  JZ @Quit
  MOV DWORD PTR [EBP + @dwFileSize], EAX //文件长度
  PUSH FILE_BEGIN
  PUSH 0
  PUSH 0
  MOV EAX, DWORD PTR [EBP + @hFile]
  PUSH EAX
  CALL DWORD PTR [EBP + @_SetFilePointer] //设置文件指针
  MOV EAX, DWORD PTR [EBP + @dwFileSize]
  CMP EAX, [EDI].TAddData.FileSize //文件长度比较
  JNZ @CRCError
  XOR EAX, EAX //CRC
  MOV EDX, DWORD PTR [EBP + @lpFileMapping] //内存指针
  MOV ECX, [EDI].TAddData.CRCAddr //数据长度
  CALL @CRC32Calc
  MOV EDX, DWORD PTR [EBP + @lpFileMapping]
  ADD EDX, [EDI].TAddData.CRCAddr
  ADD EDX, 4 //SizeOf DWORD
  MOV ECX, DWORD PTR [EBP + @dwFileSize] //文件长度
  SUB ECX, [EDI].TAddData.CRCAddr
  SUB ECX, 4 //SizeOf DWORD
  CALL @CRC32Calc
  CMP EAX, [EDI].TAddData.CRC
  JNZ @CRCError //不相等
  @CRCPassed: { CRC32校验通过 }
  MOV AL, [EDI].TAddData.AllowRepair //允许修复?
  OR AL, AL
  JZ @Quit
  CALL @CreateBackup //创建备份文件
  JMP @Quit
  //-----------------------------------------------//
  //CRC32错误处理 //
  //-----------------------------------------------//
  @CRCError:
  MOV AL, [EDI].TAddData.AllowRepair //允许修复
  OR AL, AL
  JZ @ErrorHint
  CALL @CheckBackup
  JNC @CannotRepair
  @CanRepair: { 可以自动修复 }
  MOV AL, BYTE PTR [EDI].TAddData.CanRepair
  CMP AL, crAutoRepair //自动修复
  JZ @BeginRepair
  MOV EAX, [EDI].TAddData.CanRepairDlg.uType
  PUSH EAX
  MOV EAX, EDI
  ADD EAX, [EDI].TAddData.CanRepairDlg.Caption
  PUSH EAX
  MOV EAX, EDI
  ADD EAX, [EDI].TAddData.CanRepairDlg.Text
  PUSH EAX
  PUSH 0
  CALL DWORD PTR [EBP + @_MessageBox] //弹出提示窗口
  CMP EAX, IDCANCEL //Cancel
  JZ @DoQuit
  CMP EAX, IDNO //No
  JZ @DoReturn
  @BeginRepair: { 开始修复 }
  CALL @Repair
  JC @Quit
  JMP @DoQuit
  @CannotRepair: { 无法自动修复 }
  MOV AL, BYTE PTR [EDI].TAddData.CannotRepair
  CMP AL, cnQuit //直接退出
  JZ @DoQuit
  MOV EAX, [EDI].TAddData.CannotRepairDlg.uType
  PUSH EAX
  MOV EAX, EDI
  ADD EAX, [EDI].TAddData.CannotRepairDlg.Caption
  PUSH EAX
  MOV EAX, EDI
  ADD EAX, [EDI].TAddData.CannotRepairDlg.Text
  PUSH EAX
  PUSH 0
  CALL DWORD PTR [EBP + @_MessageBox] //弹出提示窗口
  CMP EAX, IDNO //No 中断运行
  JZ @DoQuit
  MOV EAX, DWORD PTR [EDI].TAddData.CannotRepair
  CMP EAX, cnInfoOkQuit //直接退出
  JZ @DoQuit
  JMP @DoReturn //Yes 或 cnInfoOkContinue 回到原代码入口
  @ErrorHint: { 不支持修复功能 }
  MOV AL, BYTE PTR [EDI].TAddData.CrcError
  CMP AL, cnQuit //直接退出
  JZ @DoQuit
  MOV EAX, [EDI].TAddData.CrcErrorDlg.uType
  PUSH EAX
  MOV EAX, EDI
  ADD EAX, [EDI].TAddData.CrcErrorDlg.Caption
  PUSH EAX
  MOV EAX, EDI
  ADD EAX, [EDI].TAddData.CrcErrorDlg.Text
  PUSH EAX
  PUSH 0
  CALL DWORD PTR [EBP + @_MessageBox] //弹出提示窗口
  // CMP EAX, IDNO //No 中断运行
  JZ @DoQuit
  MOV EAX, DWORD PTR [EDI].TAddData.CrcError
  CMP EAX, ceInfoOkQuit //直接退出
  JZ @DoQuit
  // JMP @DoReturn //Yes 或 cnInfoOkContinue 回到原代码入口
  @DoQuit: //直接退出
  MOV EAX, 1
  MOV DWORD PTR [EBP + @bIsExit], EAX
  JMP @Quit
  @DoReturn: //转到原程序入口
  XOR EAX, EAX
  MOV DWORD PTR [EBP + @bIsExit], EAX
  JMP @Quit
  //-----------------------------------------------//
  //主代码执行结束 //
  //-----------------------------------------------//
  @Quit:
  @FreeMem: { 释放内存 }
  LEA ESI, [EBP + @lpMemTableStart] //指针表起始
  LEA EDI, [EBP + @lpMemTableEnd] //指针表结束
  @FreeMemLoop:
  CMP ESI, EDI //已结束?
  JGE @UnmapView
  MOV EAX, [ESI]
  ADD ESI, 4 //下一个
  OR EAX, EAX
  JZ @FreeMemLoop
  PUSH EAX
  CALL DWORD PTR [EBP + @_LocalFree]
  JMP @FreeMemLoop
  @UnmapView: { 关闭映射 }
  LEA ESI, [EBP + @MappingTableStart] //指针表起始
  LEA EDI, [EBP + @MappingTableEnd] //指针表结束
  @UnmapViewLoop:
  CMP ESI, EDI //已结束?
  JGE @CloseAllHandle
  MOV EAX, [ESI]
  ADD ESI, 4 //下一个
  OR EAX, EAX
  JZ @UnmapViewLoop
  PUSH EAX
  CALL DWORD PTR [EBP + @_UnmapViewOfFile]
  JMP @UnmapViewLoop
  @CloseAllHandle:{ 关闭全部句柄 }
  LEA ESI, [EBP + @HandleTableStart] //句柄表起始
  LEA EDI, [EBP + @HandleTableEnd] //句柄表结束
  @CloseAllHandleLoop:
  CMP ESI, EDI //已结束?
  JGE @ExitAddCode
  MOV EAX, [ESI]
  ADD ESI, 4 //下一个
  OR EAX, EAX
  JZ @CloseAllHandleLoop
  PUSH EAX
  CALL DWORD PTR [EBP + @_CloseHandle]
  JMP @CloseAllHandleLoop
  @ExitAddCode: //退出附加代码
  MOV EAX, DWORD PTR [EBP + @bIsExit]
  OR EAX, EAX //退出进程?
  JZ @JmpToOrgCode
  @ExitProcess: //结束程序
  MOV [ESP + $1C], EBP //保存地址修正到堆栈中的EAX部分
  POPAD
  PUSH 0
  CALL DWORD PTR [EAX + @_ExitProcess]
  @JmpToOrgCode: //转到原代码入口执行
  MOV EDI, DWORD PTR [EBP + @AddData]
  CALL @ProcessImports //处理原Import表
  JC @ExitProcess
  MOV EAX, DWORD PTR [EBP + @HInstance] //模块基址
  ADD EAX, [EDI].TAddData.OEP //原代码入口
  MOV [ESP + $1C], EAX //保存入口到堆栈中的EAX部分
  POPAD //恢复现场
  JMP EAX //转到原代码入口
  //-----------------------------------------------//
  //常量定义 //
  //-----------------------------------------------//
  @szBakExt: DB 'BK.DAT', 0
  @szToolName: DB 'RestTool.EXE', 0
  //-----------------------------------------------//
  //变量定义 //
  //-----------------------------------------------//
  //内部变量
  @Hinstance: DD 0
  @DllHandle: DD 0
  //字符串指针
  @lpMemTableStart:
  @lpFileName: DD 0
  @lpBakName: DD 0
  @lpBakExeName: DD 0
  @lpToolName: DD 0
  @lpParam: DD 0
  @lpCRC32_Table: DD 0
  @lpMemTableEnd:
  //文件句柄
  @HandleTableStart:
  @hFileMap: DD 0
  @hFile: DD 0
  @hBakFileMap: DD 0
  @hBakFile: DD 0
  @hToolFile: DD 0
  @HandleTableEnd:
  //映象视图
  @MappingTableStart:
  @lpFileMapping: DD 0
  @lpBakFileMapping: DD 0
  @MappingTableEnd:
  //其它变量
  @dwFileSize: DD 0
  @dwBakFileSize: DD 0
  @dwOrgFileCRC: DD 0
  @dwBytesWritten: DD 0
  @HKEY: DD 0
  @dwType: DD 0
  @cbData: DD 4 //注册表键值缓冲区为4字节
  @dwRegValue: DD 0
  @bIsExit: DD 0
  @AddData: DD 0
  //-----------------------------------------------//
  //自定义的Import表 //
  //-----------------------------------------------//
  @Fake_tbl:
  @Kernel32Api_tbl: DD OFFSET @Kernel32Api
  DD 0, 0
  @Kernel32Dll: DD OFFSET @szKernel32
  @Kernel32Api_tbl1: DD OFFSET @Kernel32Api
  @User32Api_tbl: DD OFFSET @User32Api
  DD 0, 0
  @User32Dll: DD OFFSET @szUser32
  @User32Api_tbl1: DD OFFSET @User32Api
  @Shell32Api_tbl: DD OFFSET @Shell32Api
  DD 0, 0
  @Shell32Dll: DD OFFSET @szShell32
  @Shell32Api_tbl1: DD OFFSET @Shell32Api
  @AdvApi32Api_tbl: DD OFFSET @AdvApi32Api
  DD 0, 0
  @AdvApi32Dll: DD OFFSET @szAdvApi32
  @AdvApi32Api_tbl1: DD OFFSET @AdvApi32Api
  DD 0, 0, 0, 0, 0 //结束
  @Lookup_tbl: //地址表
  @Kernel32Api:
  @_GetProcAddress: DD OFFSET @szGetProcAddress
  @_LoadLibrary: DD OFFSET @szLoadLibrary
  @_GetModuleHandle: DD OFFSET @szGetModuleHandle
  @_GetModuleFileName: DD OFFSET @szGetModuleFileName
  @_FreeLibrary: DD OFFSET @szFreeLibrary
  @_ExitProcess: DD OFFSET @szExitProcess
  @_LocalAlloc: DD OFFSET @szLocalAlloc
  @_LocalFree: DD OFFSET @szLocalFree
  @_CreateFile: DD OFFSET @szCreateFile
  @_SetFilePointer: DD OFFSET @szSetFilePointer
  @_CloseHandle: DD OFFSET @szCloseHandle
  @_CreateFileMapping: DD OFFSET @szCreateFileMapping
  @_MapViewOfFile: DD OFFSET @szMapViewOfFile
  @_UnmapViewOfFile: DD OFFSET @szUnmapViewOfFile
  @_WriteFile: DD OFFSET @szWriteFile
  @_DeleteFile: DD OFFSET @szDeleteFile
  @_CreateDirectory: DD OFFSET @szCreateDirectory
  @_GetTempPath: DD OFFSET @szGetTempPath
  @_GetSystemDirectory: DD OFFSET @szGetSystemDirectory
  @_GetWindowsDirectory: DD OFFSET @szGetWindowsDirectory
  @_WinExec: DD OFFSET @szWinExec
  @_lstrcpy: DD OFFSET @szlstrcpy
  @_lstrcpyn: DD OFFSET @szlstrcpyn
  @_lstrcat: DD OFFSET @szlstrcat
  @_lstrlen: DD OFFSET @szlstrlen
  DD 0
  @User32Api:
  @_MessageBox: DD OFFSET @szMessageBox
  DD 0
  @Shell32Api:
  @_ShellExecute: DD OFFSET @szShellExecute
  DD 0
  @Advapi32Api:
  @_RegOpenKeyEx: DD OFFSET @szRegOpenKeyEx
  @_RegQueryValueEx: DD OFFSET @szRegQueryValueEx
  @_RegCloseKey: DD OFFSET @szRegCloseKey
  DD 0
  @Name_tbl: //名字表
  @szKernel32: DB 'kernel32.dll', 0
  @szGetProcAddress: DW 0
  DB 'GetProcAddress', 0
  @szLoadLibrary: DW 0
  DB 'LoadLibraryA', 0
  @szGetModuleHandle: DW 0
  DB 'GetModuleHandleA', 0
  @szGetModuleFileName: DW 0
  DB 'GetModuleFileNameA', 0
  @szFreeLibrary: DW 0
  DB 'FreeLibrary', 0
  @szExitProcess: DW 0
  DB 'ExitProcess', 0
  @szLocalAlloc: DW 0
  DB 'LocalAlloc', 0
  @szLocalFree: DW 0
  DB 'LocalFree', 0
  @szCreateFile: DW 0
  DB 'CreateFileA', 0
  @szSetFilePointer: DW 0
  DB 'SetFilePointer', 0
  @szCloseHandle: DW 0
  DB 'CloseHandle', 0
  @szCreateFileMapping: DW 0
  DB 'CreateFileMappingA', 0
  @szMapViewOfFile: DW 0
  DB 'MapViewOfFile', 0
  @szUnmapViewOfFile: DW 0
  DB 'UnmapViewOfFile', 0
  @szWriteFile: DW 0
  DB 'WriteFile', 0
  @szDeleteFile: DW 0
  DB 'DeleteFileA', 0
  @szCreateDirectory: DW 0
  DB 'CreateDirectoryA', 0
  @szGetTempPath: DW 0
  DB 'GetTempPathA', 0
  @szGetSystemDirectory: DW 0
  DB 'GetSystemDirectoryA', 0
  @szGetWindowsDirectory: DW 0
  DB 'GetWindowsDirectoryA', 0
  @szWinExec: DW 0
  DB 'WinExec', 0
  @szlstrcpy: DW 0
  DB 'lstrcpyA', 0
  @szlstrcpyn: DW 0
  DB 'lstrcpynA', 0
  @szlstrcat: DW 0
  DB 'lstrcatA', 0
  @szlstrlen: DW 0
  DB 'lstrlenA', 0
  @szUser32: DB 'user32.dll', 0
  @szMessageBox: DW 0
  DB 'MessageBoxA', 0
  @szShell32: DB 'shell32.dll', 0
  @szShellExecute: DW 0
  DB 'ShellExecuteA', 0
  @szAdvapi32: DB 'advapi32.dll', 0
  @szRegOpenKeyEx: DW 0
  DB 'RegOpenKeyExA', 0
  @szRegQueryValueEx: DW 0
  DB 'RegQueryValueExA', 0
  @szRegCloseKey: DW 0
  DB 'RegCloseKey', 0
  @Fake_tbl_End:
  //-----------------------------------------------//
  //内部子过程 //
  //-----------------------------------------------//
  { 数据解密子过程 }
  //ESI -> 数据块地址
  //EAX -> XOR 值
  //ECX -> 长度
  @DataDecode:
  @DataXor:
  MOV EBX, [ESI]
  OR EBX, EBX
  JZ @XorZero
  XOR [ESI], EAX
  @XorZero:
  ADD ESI, 4
  LOOP @DataXor
  RET
  { 查询注册表键值确定是否允许CRC32校验 }
  @QueryReg: { 查询注册表 }
  @RegOpen:
  MOV EDI, DWORD PTR [EBP + @AddData]
  MOV AL, BYTE PTR [EDI].TAddData.AllowRegQuery
  OR AL, AL
  JZ @Reg_Succ
  LEA EAX, [EBP + @hKey]
  PUSH EAX
  PUSH KEY_READ
  PUSH 0
  MOV EAX, EDI
  ADD EAX, [EDI].TAddData.RegSubKey
  PUSH EAX
  MOV EAX, [EDI].TAddData.RegKey
  PUSH EAX
  CALL DWORD PTR [EBP + @_RegOpenKeyEx] //打开注册表子键
  CMP EAX, ERROR_SUCCESS
  JNZ @Reg_Succ
  @QueryValue:
  LEA EAX, [EBP + @cbData]
  PUSH EAX
  LEA EAX, [EBP + @dwRegValue]
  PUSH EAX
  LEA EAX, [EBP + @dwType]
  PUSH EAX
  PUSH 0
  MOV EAX, EDI
  ADD EAX, [EDI].TAddData.RegValue
  PUSH EAX
  MOV EAX, DWORD PTR [EBP + @hKey]
  PUSH EAX
  CALL DWORD PTR [EBP + @_RegQueryValueEx] //查询键值
  CMP EAX, ERROR_SUCCESS
  JZ @RegClose
  XOR EAX, EAX
  MOV DWORD PTR [EBP + @dwRegValue], EAX
  @RegClose:
  MOV EAX, DWORD PTR [EBP + @hKey]
  PUSH EAX
  CALL DWORD PTR [EBP + @_RegCloseKey] //关闭注册表
  MOV EAX, DWORD PTR [EBP + @dwRegValue]
  OR EAX, EAX
  JNZ @Reg_Fail
  @Reg_Succ:
  CLC
  RET
  @Reg_Fail:
  STC
  RET
  { 处理原Import表 }
  @ProcessImports:
  PUSH EDI
  MOV ESI, [EDI].TAddData.iAddress
  OR ESI, ESI
  JZ @Import_Succ
  MOV EDX, DWORD PTR [EBP + @HInstance]
  ADD ESI, EDX
  @Dir_loop:
  CALL @ProcessImportDir
  JC @Import_Fail
  ADD ESI, SizeOfImportDir
  CMP DWORD PTR [ESI].TImageImportDirectory.Name, 0
  JNZ @Dir_loop
  @Import_Succ:
  CLC
  POP EDI
  RET
  @Import_Fail:
  STC
  POP EDI
  RET
  { 处理Import表目录 }
  //ESI -> IMPORT_DIRECTORY_VA
  //EDX -> IMAGEBASE
  @ProcessImportDir:
  MOV ECX, [ESI].TImageImportDirectory.Misc.OriginalFirstThunk //ECX->原地址表
  MOV EDI, [ESI].TImageImportDirectory.FirstThunk //EDI->结果地址表
  OR ECX, ECX
  JNZ @lr_ok
  MOV ECX, EDI
  @lr_ok:
  ADD ECX, EDX
  ADD EDI, EDX
  MOV EAX, [ESI].TImageImportDirectory.Name //EAX->Dll Name
  ADD EAX, EDX
  PUSH ECX
  PUSH EDX
  PUSH EAX
  CALL DWORD PTR [EBP + @_LoadLibrary]
  POP EDX
  POP ECX
  OR EAX, EAX
  JZ @iret_error
  MOV DWORD PTR [EBP + @DllHandle], EAX
  @lookup_loop:
  MOV EBX, [ECX]
  OR EBX, EBX
  JZ @iret_success
  TEST EBX, $80000000 //按序号输入
  JNZ @import_by_ordinal
  ADD EBX, EDX
  INC EBX
  INC EBX
  @import_by_ordinal:
  AND EBX, $7FFFFFFF
  PUSH ECX
  PUSH EDX
  PUSH EBX
  MOV EAX, DWORD PTR [EBP + @DllHandle]
  PUSH EAX
  CALL DWORD PTR [EBP + @_GetProcAddress]
  POP EDX
  POP ECX
  OR EAX,EAX
  JZ @iret_error
  STOSD
  ADD ECX, 4 //下一个入口
  JMP @lookup_loop
  @iret_success:
  CLC
  RET
  @iret_error:
  STC
  RET
  { 初始化CRC32表 }
  @MakeCRC32Table:
  PUSH 1024
  PUSH LMEM_FIXED
  CALL DWORD PTR [EBP + @_LocalAlloc]
  OR EAX, EAX
  JZ @MakeCRC32_Error
  MOV DWORD PTR [EBP + @lpCRC32_Table], EAX
  MOV EDX, EAX
  XOR EBX, EBX
  @MakeCRC32Loop:
  CMP EBX, $100
  JE @MakeCRC32_Succ
  MOV EAX, EBX
  MOV ECX, 8
  @MakeLoop:
  TEST EAX, 1
  JZ @MakeIsZero
  SHR EAX, 1
  XOR EAX, $EDB88320
  JMP @MakeNext
  @MakeIsZero:
  SHR EAX, 1
  @MakeNext:
  LOOP @MakeLoop
  MOV DWORD PTR [EDX], EAX
  ADD EDX, 4
  INC EBX
  JMP @MakeCRC32Loop
  @MakeCRC32_Succ:
  CLC
  RET
  @MakeCRC32_Error:
  STC
  RET
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值