質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

3955閲覧

C# WriteProcessMemoryで、ポインタ+オフセットが指定できない

Susanoo2442

総合スコア153

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2016/11/24 15:24

VisualStudio2015
C#
プラットフォーム64bit
使用デバッガ:CheatEngine 6.4

現在リバースエンジニアリングスキルを上げるために
プログラムの解析ツールを制作しております。
解析ツールの目的は
対象となるプログラムのメモリを書き換えて対象となるプログラムのステータスを変更する事です。
現在の開発段階としましては
まず、デバッガで対象のプロセスを解析します。
次に、対象のメモリアドレスを見つけます。
そして、そのメモリアドレスを
WriteProcessMemroyの第二引数に指定して、第三引数で実際に書き換えるメモリを指定して
メモリを書き換えています。
ここまでは、実際に上手くメモリが書き換わり、対象のプログラムのステータスが変わっていました。

問題は次で
対象のプログラムは起動する度に、メモリアドレスが変動します。
そこで、ポインタとオフセットを解析してメモリが変動しても目的のメモリアドレスを
簡単に割り出せるようにしました。

そして、そのポインタとオフセットを加算した変数を
WriteProcessMemoryの第二引数に渡しましたが
値は変わっておりませんでした。
しかし、if文でエラーチェックをしているのですが
コンソールには成功!と表示されていましたので
関数自体は、成功しているのではと思います。

WriteProcessMemoryにポインタとオフセットを指定して目的の
メモリを書き換えるにはどうするばよろしいでしょうか?
アドバイス頂けたらと思います。

下記がソースコードです。

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading.Tasks; 9using System.Windows.Forms; 10using System.Diagnostics; 11using System.Runtime.InteropServices; 12 13namespace NUNS4{ 14 15 16 17 18 public partial class Form1 : Form { 19 20 21 22 [DllImport("kernel32.dll")] 23 static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId); 24 25 26 27 28 [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 29 static extern IntPtr VirtualAllocEx(int hProcess, long lpAddress, 30 int dwSize, AllocationType flAllocationType, MemoryProtection flProtect); 31 32 [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 33 static extern bool VirtualFreeEx(int hProcess, long lpAddress, 34 int dwSize, FreeType dwFreeType); 35 36 37 38 [DllImport("kernel32.dll", SetLastError = true)] 39 static extern bool WriteProcessMemory(int hProcess, long lpBaseAddress, 40 byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesWritten); 41 42 43 44 private enum ProcessAccessFlags : uint 45 { 46 All = 0x001F0FFF, 47 Terminate = 0x00000001, 48 CreateThread = 0x00000002, 49 VMOperation = 0x00000008, 50 PROCESS_VM_READ = 0x10, 51 VMWrite = 0x00000020, 52 DupHandle = 0x00000040, 53 SetInformation = 0x00000200, 54 QueryInformation = 0x00000400, 55 Synchronize = 0x00100000 56 } 57 58 59 [Flags] 60 public enum AllocationType 61 { 62 Commit = 0x1000, 63 Reserve = 0x2000, 64 Decommit = 0x4000, 65 Release = 0x8000, 66 Reset = 0x80000, 67 Physical = 0x400000, 68 TopDown = 0x100000, 69 WriteWatch = 0x200000, 70 LargePages = 0x20000000 71 } 72 73 [Flags] 74 public enum MemoryProtection 75 { 76 Execute = 0x10, 77 ExecuteRead = 0x20, 78 ExecuteReadWrite = 0x40, 79 ExecuteWriteCopy = 0x80, 80 NoAccess = 0x01, 81 ReadOnly = 0x02, 82 ReadWrite = 0x04, 83 WriteCopy = 0x08, 84 GuardModifierflag = 0x100, 85 NoCacheModifierflag = 0x200, 86 WriteCombineModifierflag = 0x400 87 } 88 89 90 91 [Flags] 92 public enum FreeType 93 { 94 Decommit = 0x4000, 95 Release = 0x8000, 96 } 97 98 99 System.Diagnostics.Process[] ps = 100 System.Diagnostics.Process.GetProcessesByName("Tutorial-x86_64"); 101 IntPtr aPtr; 102 int aaa; 103 104 105 106 107 108 109 110 111 public Form1(){ 112 InitializeComponent(); 113 114 115 foreach (System.Diagnostics.Process p in ps) 116 { 117 Console.WriteLine("{0}/{1}", p.Id, p.MainWindowTitle); 118 aaa = p.Id; 119 } 120 121 122 123 if ((aPtr = OpenProcess(ProcessAccessFlags.All, false, aaa)) == null) 124 { 125 Console.WriteLine("ハンドルが取得されませんでした"); 126 } 127 else 128 { 129 Console.WriteLine("ハンドルが取得されました"); 130 Console.WriteLine(aPtr); 131 } 132 133 134 135 } 136 137 private void button1_Click(object sender, EventArgs e) 138 { 139 140 141 long OffSet = 0x790; // オフセット 142 long PointerAddress = 0x1002F79F0;// ポインタアドレス 143 int faste = 0; 144 byte[] newvalue3 = { 0x64 }; 145 long FinalAddress = OffSet + PointerAddress; 146 147 148 Console.WriteLine("コマンドオン"); 149 VirtualAllocEx((int)aPtr, (long)PointerAddress, 1, AllocationType.Commit, MemoryProtection.ExecuteReadWrite); 150 VirtualFreeEx((int)aPtr, (long)PointerAddress, 0, FreeType.Decommit); 151 152 if ((WriteProcessMemory((int)aPtr, (long)FinalAddress, newvalue3, 1, ref faste)) == false) 153 { 154 155 156 Console.WriteLine("プログラム改ざん失敗!"); 157 } 158 159 else 160 { 161 Console.WriteLine("プログラム改ざん成功!"); 162 163 } 164 165 } 166 } 167} 168

それでは、宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yohhoy

2016/11/25 08:57 編集

関数のP/Invoke宣言が適切ではありません。ポインタ型にIntPtrを使わないと、64bit環境だとまともに動かないのでは? http://www.pinvoke.net/default.aspx/kernel32.writeprocessmemory 追記:IntPtrの件は、VirtualAllocEx, VirtualFreeEx, WriteProcessMemory全てを見直す必要があります。また質問文中も修正後コードに更新された方が良いです。
Susanoo2442

2016/11/25 08:49

IntPtrを使用しましたが書き換える事は出来ませんでした。コーディングにも問題はないと思われるのですが、何が原因かさっぱり分かりません。
guest

回答1

0

ベストアンサー

最初のステップでは、対象のプロセスのどこ(仮想アドレス)を書き換えるべきかは、目で見て確認したと言う事ですよね?で、次のステップとして:

対象のプログラムは起動する度に、メモリアドレスが変動します。

そこで、ポインタとオフセットを解析してメモリが変動しても目的のメモリアドレスを
簡単に割り出せるようにしました。

ここで言う「ポインタ」と言うのは、対象のプロセスのとある場所(例では0x1002F79F0)に格納されているのだと思いますが、VirtualAllocExでそれを見えるようにしようとして、しかし実際にはFinalAddressは単にPointerAddressとOffsetから固定的に計算したアドレスに書いているように読めます。

補足:
対象が64ビットなら問題ありませんが、IntPtrを使った方が良いのはyohhoyさんの指摘の通りです。但し、間接ポインタの計算方法も32/64の違いで注意が必要ですし、対象のプロセスが32/64なのかによっても違うので、真面目にやると結構大変です。

投稿2016/12/08 04:21

kekyo

総合スコア21

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Susanoo2442

2017/01/30 02:43

ベストアンサー遅くなりました。 全ての原因はReadProcessMemoryを記述して無かった事でした。 ReadProcessMemoryで目的の値を読み取って そこから、オフセットの処理などを行わなければいけなかったみたいです。 ありがとうございました。
kekyo

2017/01/30 02:45

:+1:
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問