当前位置: 首页 > article >正文

一种动态地址的查询

背景

当我们注入一个进程,通过函数地址进行call时经常会遇到这样的一个问题。对方程序每周四会自动更新。更新后之前的函数地址就变化了,然后需要重新找地址。所以,我就使用了一个动态查询的方式。

第一步:先为需要call的函数生成特征码。特征码其实就是反汇编后,去掉地址,只留操作符。


function make_search(v: dword; ms: TMemoryStream; maxsize: integer): string;
var
  offset: dword;
  isnot_ret: boolean;
  description: string;
begin
  ms.Clear;
  Result := '';
  offset := v;
  isnot_ret := true;
  while isnot_ret do
    begin
      isnot_ret := pbyte(offset)^ <> $C3;
      disassemble_find(offset, description, ms);
      if Result <> '' then
        Result := Result + #13#10;
      Result := Result + description;
      if ms.Size > 1024 then
        Break;
    end;
end;

disassemble_find 函数的行数太多了。

function disassemble_find(var offset: dword; var description: string; ms_find: TMemoryStream): string; overload;
var
  memory: TMemory;
  actualread: dword;
  startoffset: dword;
  tempresult: string;
  tempst: string;
  wordptr: ^word;
  dwordptr: ^dword;
  dwordptr2: ^dword;
  singleptr: ^single;
  doubleptr: ^double;
  extenedptr: ^extended;
  int64ptr: ^int64;
  i, j: integer;

  prefix: TPrefix;
  prefix2: TPrefix;
  isprefix: boolean;

  last: dword;
  foundit: boolean;
  search_size: integer;
  str_tmp: string;
begin
  search_size := 0;
  result := inttohex(offset, 8) + ' - ';

  isprefix := true;
  prefix := [$F0, $F2, $F3, $2E, $36, $3E, $26, $64, $65, $66, $67];
  prefix2 := [];

  //forced 16-bit
  if mode16 then
    prefix2 := prefix2 + [$66];

  startoffset := offset;

  readmemory(pointer(offset), addr(memory), 24, actualread);

  /

  if actualread > 0 then
    begin
      //I HATE THESE...   (I propably will not add them all, but I'll see how far I get)

      while isprefix do
        begin
          inc(offset);
          if memory[0] in prefix then
            begin
              result := result + inttohexs(memory[0], 2) + ' ';
              isprefix := true;
              inc(startoffset);
              prefix2 := prefix2 + [memory[0]];
              ReadMemory(pointer(offset), addr(memory), 24, actualread);
            end
          else
            isprefix := false;
        end;

      if $F0 in prefix2 then tempresult := 'lock ';
      if $F2 in prefix2 then tempresult := tempresult + 'repne ';
      if $F3 in prefix2 then tempresult := tempresult + 'repe ';

      case memory[0] of //opcode
        $00:
          begin
            description := 'Add';
            tempresult := tempresult + 'add ' + MODRM(memory, prefix2, 1, 2, last) + r8(memory[1]);
            inc(offset, last - 1);
          end;

        $01:
          begin
            description := 'Add';
            if $66 in prefix2 then
              tempresult := tempresult + 'ADD ' + MODRM(memory, prefix2, 1, 1, last) + r16(memory[1])
            else
              tempresult := tempresult + 'ADD ' + MODRM(memory, prefix2, 1, 0, last) + r32(memory[1]);
            inc(offset, last - 1);

          end;

        $02:
          begin
            description := 'Add';
            tempresult := tempresult + 'ADD ' + r8(memory[1]) + ',' + MODRM(memory, prefix2, 1, 2, last);
            tempresult := copy(tempresult, 0, length(tempresult) - 1);
            inc(offset, last - 1);
          end;

        $03:
          begin
            description := 'Add';
            if $66 in prefix2 then
              tempresult := tempresult + 'ADD ' + r16(memory[1]) + ',' + MODRM(memory, prefix2, 1, 1, last)
            else
              tempresult := tempresult + 'ADD ' + r32(memory[1]) + ',' + MODRM(memory, prefix2, 1, 0, last);
            tempresult := copy(tempresult, 0, length(tempresult) - 1);
            inc(offset, last - 1);
          end;

        $04:
          begin
            description := 'Add x to y';
            tempresult := tempresult + 'ADD AL,' + inttohexs(memory[1], 2);
            inc(offset);
          end;

        $05:
          begin
            description := 'Add x to y';
            wordptr := @memory[1];
            dwordptr := @memory[1];
            if $66 in prefix2 then
              begin
                tempresult := tempresult + 'ADD AX,' + inttohexs(wordptr^, 4);
                inc(offset, 2);
              end
            else
              begin
                tempresult := tempresult + 'ADD EAX,' + inttohexs(dwordptr^, 8);
                inc(offset, 4);
              end;
          end;

第二步:查询函数地址

function search_address(ms_search: TMemoryStream; sl: tstringlist): string;
var
  idx, i: integer;
  ms: TMemoryStream;
  Mem: TMemoryBasicInformation;
  dwProtect, temp: cardinal;
  msize: dword;
  canread, willVirtualProtect: boolean;

  procedure dosearch;
  var
    count, idx, i, l: integer;
    s: string;
    ms_old: TMemoryStream;
    ms: TMemoryStream;
  begin
    ms_search.Position := 0;
    ms_search.Read(count, sizeof(ms_search));
    for i := 1 to count do
      begin
        ms := TMemoryStream.Create;
        ms_old := TMemoryStream.Create;

        ms_search.Read(l, sizeof(l));
        setlength(s, l);
        ms_search.Read(s[1], l);
        ms_search.Read(l, sizeof(l));
        ms_old.CopyFrom(ms_search, l);

        ms_search.Read(l, sizeof(l));
        ms.CopyFrom(ms_search, l);

        //if SameText('Py_GetVersion', s) then
        begin
          idx := search_ms(integer(Mem.BaseAddress), Mem.RegionSize, ms_old);
          if idx < 0 then
            begin
              idx := search_ms(integer(Mem.BaseAddress), Mem.RegionSize, ms);
            end;
          if idx >= 0 then
            begin
              sl.AddObject(s, pointer(idx));
              if Result <> '' then
                Result := Result + #13#10;
              Result := Result + s + '=' + IntToStr(idx - integer(Mem.BaseAddress));
            end;
        end;
        FreeAndNil(ms);
        FreeAndNil(ms_old);
      end;
  end;
begin
  Result := '';
  idx := -1;
  if length(Mems) <= 0 then
    u_mem.test;
  for i := 0 to high(Mems) do
    begin
      if SameText('mhmain.dll', GetItemFilePath(Mems[i], Modules)) then
        if Mems[i].RegionSize > 1024 * 1024 * 4 then
          begin
            Mem := Mems[i];
            idx := i;
            Break;
          end;
    end;
  if idx < 0 then
    exit;
  canread := not IsBadReadPtr(mem.BaseAddress, mem.RegionSize);
  if not canread then
    begin
      if VirtualProtect(mem.BaseAddress, mem.RegionSize, PAGE_EXECUTE_READWRITE, @dwProtect) then
        begin
          canread := true;
          willVirtualProtect := true;
        end;
    end;
  if canread then
    begin
      dosearch;
    end;
  if willVirtualProtect then
    VirtualProtect(mem.BaseAddress, mem.RegionSize, dwProtect, @temp);
end;
 

注意

同一个函数可能查到多个地址,但是可以根据多个地址进行校验。命中的范围最集中的那个范围中的地址,一般都是正确的地址。


http://www.kler.cn/a/550174.html

相关文章:

  • 2.17学习,双向循环链表
  • BFS广度优先搜索——994.腐烂的橘子
  • 通过VSCode直接连接使用 GPT的编程助手
  • 以下是 HTML 与 HTML5 的核心区别及从基础到高级的总结:
  • window中git bash使用conda命令
  • 什么是3D视觉无序抓取?
  • 海康摄像头IPV6模式,手动,自动,路由公告
  • 【力扣Hot 100】回溯1
  • Maven 项⽬⽣命周期
  • 数字化转型实战:Odoo+工业物联网技术破解江苏食品制造行业三大核心痛点
  • Java 运行时常量池笔记(详细版
  • 基础算法# 求一个数的二进制表示当中有几个1 (C++)
  • 解惑Python:一文解决osgeo库安装失败问题
  • 多模态特征提取与融合助力高光谱+LiDAR数据分类性能飞跃
  • 图片属性——位深度
  • 基站天线的优化策略
  • Java 集合数据处理技巧:使用 Stream API 实现多种操作
  • 2025年保安员职业资格考试模拟真题及答案
  • remix中为什么Dev -Ganache Provider没有了; remix中区块链常见的链接方式有哪些
  • 如何做好项目变更管理