Perl、Python、またはRubyプログラムを作成して、Windows上の別のプロセスのメモリを変更する方法
-
06-07-2019 - |
質問
Perl、Python、またはRubyを使用して別のプロセスのメモリ(おそらくヒープ、データとコードデータの両方)で0x12345678を探すようにプログラムを作成できるかどうか、それが見つかった場合、0x00000000に変更しますか?それはチートエンジンに似ており、Windowsでそのようなことができます。
解決
最初はこれは不可能だと思っていましたが、ブライアンのコメントを見た後、CPANとloを検索して見ました。 Win32 :: Process :: Memory :
C:\> ppm install Win32::Process::Info
C:\> ppm install Win32::Process::Memory
モジュールは明らかに ReadProcessMemory
機能:私の試みの1つです:
#!/usr/bin/perl
use strict; use warnings;
use Win32;
use Win32::Process;
use Win32::Process::Memory;
my $process;
Win32::Process::Create(
$process,
'C:/opt/vim/vim72/gvim.exe',
q{},
0,
NORMAL_PRIORITY_CLASS,
q{.}
) or die ErrorReport();
my $mem = Win32::Process::Memory->new({
pid => $process->GetProcessID(),
access => 'read/query',
});
$mem->search_sub( 'VIM', sub {
print $mem->hexdump(最初はこれは不可能だと思っていましたが、ブライアンのコメントを見た後、CPANとloを検索して見ました。 Win32 :: Process :: Memory :
C:\> ppm install Win32::Process::Info
C:\> ppm install Win32::Process::Memory
モジュールは明らかに ReadProcessMemory
機能:私の試みの1つです:
C:\Temp> proc
0052A580 : 56 49 4D 20 2D 20 56 69 20 49 4D 70 72 6F 76 65 : VIM - Vi IMprove
0052A590 : 64 20 37 2E 32 20 28 32 30 30 38 20 41 75 67 20 : d 7.2 (2008 Aug
0052A5F0 : 56 49 4D 52 55 4E 54 49 4D 45 3A 20 22 00 : VIMRUNTIME: ".
0052A600 : 20 20 66 61 6C 6C 2D 62 61 63 6B 20 66 6F 72 20 : fall-back for
0052A610 : 24 56 : $V
出力:
<*>[0], 0x20), "\n";
});
sub ErrorReport{
Win32::FormatMessage( Win32::GetLastError() );
}
END { $process->Kill(0) if $process }
出力:
<*>他のヒント
プログラムをデバッガーとしてプロセスにアタッチしている場合、適切なAPIのラッパーが存在する場合はそれらの言語で可能か、ctypes(for python)。ただし、高レベルの言語では高レベルのデータ型を低レベルのデータ型などに変換する方法を考慮する必要があるため、より低レベルの言語で行う方が簡単な場合があります。
プロセスで OpenProcess を呼び出して開始します適切なアクセス権を要求してデバッグするには(マシンの管理者である必要があります/アクセスするにはかなり高い権限が必要です)。その後、 ReadProcessMemory のような関数を呼び出すことができるはずです。および WriteProcessMemory は、そのプロセスの読み取りと書き込みを行いますメモリ。
[編集] これは、別のプロセスのアドレス空間からメモリを正常に読み取る関数の簡単なpythonの概念実証です。
import ctypes
import ctypes.wintypes
kernel32 = ctypes.wintypes.windll.kernel32
# Various access flag definitions:
class Access:
DELETE = 0x00010000
READ_CONTROL= 0x00020000
SYNCHRONIZE = 0x00100000
WRITE_DAC = 0x00040000
WRITE_OWNER = 0x00080000
PROCESS_VM_WRITE = 0x0020
PROCESS_VM_READ = 0x0010
PROCESS_VM_OPERATION = 0x0008
PROCESS_TERMINATE = 0x0001
PROCESS_SUSPEND_RESUME = 0x0800
PROCESS_SET_QUOTA = 0x0100
PROCESS_SET_INFORMATION = 0x0200
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_DUP_HANDLE = 0x0040
PROCESS_CREATE_THREAD = 0x0002
PROCESS_CREATE_PROCESS = 0x0080
def read_process_mem(pid, address, size):
"""Read memory of the specified process ID."""
buf = ctypes.create_string_buffer(size)
gotBytes = ctypes.c_ulong(0)
h = kernel32.OpenProcess(Access.PROCESS_VM_READ, False, pid)
try:
if kernel32.ReadProcessMemory(h, address, buf, size, ctypes.byref(gotBytes)):
return buf
else:
# TODO: report appropriate error GetLastError
raise Exception("Failed to access process memory.")
finally:
kernel32.CloseHandle(h)
メモリ内のどこを検索するかを決定する必要があることに注意してください-そのアドレス空間のほとんどはマップされません、プログラムコード、dllなどのようなものを検索するいくつかの標準オフセットがあると思います
さて、楽しいのは他のプロセスのメモリにアクセスすることです。 CheatEngineは、メモリ保護を無効にする仮想マシンの下でOS全体を実行することでそれを実現します。また、「デバッガーの下で実行する」モデルもあります。これは、一般に、昇格した特権で、変更するアプリケーションの子プロセスとしてターゲットアプリケーションを起動することを意味します。たくさんの楽しいものについては、 Win32 API をご覧ください。それについて。
Perlでは、必要なアクセス権を取得したら、 Win32 :: Security :: Raw 。
プロセスインジェクション、遅延ロードライブラリなどを使用してこれを行う方法があります。
あなたがリストしたツールからそれをしているのを見ません。これはCとアセンブラーの国であり、あなたをウイルス作成領域に引き込み始めています。動作させると、アンチウイルスパッケージは実行を拒否し、分離を試みます。だから、あなたは本当にこれをしたいのです。
&quot;パワーには多くの利点があります....&quot;
幸運
リストされている言語のいずれかでプロセス全体を実装することは可能ですが、メモリスキャンにはコンパイルされた言語の方が適しています(他に方法がない場合は速度を考慮する)。特定のゲーム用に調整されたSigScanというdll(ソース付き)が利用可能ですが、おそらく最小限の労力でニーズに合わせて変更できます。
Brianの正解に基づいて構築したのは、DLLを使用してpythonからアドレスを取得する簡単で汚い例です。 もちろん、これはDLLの実装に固有のものです。 &quot;モジュール名&quot;通常、チートエンジン&quot;列挙DLLとシンボル&quot;に表示されるdll名です。ダイアログ。
ガイドラインとしてのブライアンの例と MSDN では、独自のWriteProcessMemoryメソッドでこれを簡単に拡張できます。
import win32defines
import win32process
import win32gui
from ctypes import *
SigScan = cdll.SigScan
kernel32 = windll.kernel32
addresses = {"Value1" : {"sigArg1" : "b0015ec390518b4c24088d4424005068",
"sigArg2" : 36,
"address" : None,
"size" : 32
},
"Value2" :{"sigArg1" : "3b05XXXXXXXX741285c0",
"sigArg2" : None,
"address" : None,
"size" : 32
}
}
def read_process_mem(pid, address, size):
"""Read memory of the specified process ID."""
buf = create_string_buffer(size)
gotBytes = c_ulong(0)
h = kernel32.OpenProcess(win32defines.PROCESS_VM_READ, False, pid)
try:
if kernel32.ReadProcessMemory(h, address, buf, size, byref(gotBytes)):
return buf
else:
# TODO: report appropriate error GetLastError
raise Exception("Failed to access process memory.")
finally:
kernel32.CloseHandle(h)
if __name__ == "__main__":
pid, id = None, None
## HWND
hwnd = win32gui.FindWindowEx(0, 0, 0, "Window Name here")
## pid
pid = win32process.GetWindowThreadProcessId(hwnd)[-1]
## Initialize the sigscan dll
SigScan.InitializeSigScan(pid, "Module Name")
## Find all the addresses registered
for key in addresses.keys():
addresses[key]["address"] = SigScan.SigScan(addresses[key]["sigArg1"],
addresses[key]["sigArg2"])
## Allow the scanner to clean up
SigScan.FinalizeSigScan()
for key in addresses.keys():
if addresses[key]["address"] != None:
print repr(read_process_mem(pid, addresses[key]["address"],
addresses[key]["size"]).raw)
Proc :: Memory とその基礎となるライブラリ libvas この目的のため。 Windowsの内部で {Read、Write} ProcessMemory
を呼び出すだけですが、他のプラットフォームもサポートしています。例:
my $mem = Proc::Memory->new(pid => $);
$mem->poke(0x12345678, 'L') = 12;