网站的运营与维护,12306网站是是阿里巴巴做的吗,网页工程师培训机构,苏州好的网络科技公司背景
当我们注入一个进程#xff0c;通过函数地址进行call时经常会遇到这样的一个问题。对方程序每周四会自动更新。更新后之前的函数地址就变化了#xff0c;然后需要重新找地址。所以#xff0c;我就使用了一个动态查询的方式。
第一步#xff1a;先为需要call的函数生…背景
当我们注入一个进程通过函数地址进行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 Ill 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;
注意
同一个函数可能查到多个地址但是可以根据多个地址进行校验。命中的范围最集中的那个范围中的地址一般都是正确的地址。