質問編集履歴

1

構造体を32bit用に変更、読み書きできるメモリの確保コードの追加

2021/09/16 13:27

投稿

shinyama
shinyama

スコア1

title CHANGED
File without changes
body CHANGED
@@ -124,17 +124,130 @@
124
124
  public int iGroup;
125
125
  }
126
126
 
127
+ ```
127
128
 
128
-   
129
+ ###9/16修正後
130
+ ソフトが落ちることはなくなりましたが、textの中身は””状態で取得することができませんでした。。
131
+ 構造体はすべてintに変更しています
132
+ 〇主コード抜粋
133
+ ```
134
+ //listViewのプロセスIDを取得する
129
135
 
136
+ int dwProcessId;
130
137
 
138
+ GetWindowThreadProcessId(hWnd, out dwProcessId);
131
139
 
140
+ // 取得したプロセスIDをオープンする
132
141
 
142
+ IntPtr hProcess;
133
143
 
144
+ hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, (uint)dwProcessId);
134
145
 
146
+ //必要なリストビューアイテムのテキストを格納するために、文字列にバッファを割り当て
147
+
148
+ var textBufferPtr = VirtualAllocEx(hProcess, IntPtr.Zero,MAX_LVMSTRING,AllocationType.Commit, MemoryProtection.ReadWrite);
149
+
150
+
151
+ //listViewの行数
152
+
153
+ int itemId = 2;
154
+
155
+ //listViewの列数
156
+
157
+ int subItemId = 2;
158
+
159
+
160
+
161
+ //構造体のnew
162
+
163
+ tagLVITEMA lvItem = new tagLVITEMA();
164
+
165
+ lvItem.mask = LVIF_TEXT;
166
+
167
+ lvItem.cchTextMax = (int)MAX_LVMSTRING;
168
+
169
+ lvItem.iItem = itemId;
170
+
171
+ lvItem.iSubItem = subItemId;
172
+
173
+
174
+
175
+ //リモートプロセスでLVITEM構造にメモリを割り当て
176
+
177
+ int lvItemSize = Marshal.SizeOf(lvItem);
178
+
179
+ var lvItemBufferPtr = VirtualAllocEx(hProcess, IntPtr.Zero,(uint)lvItemSize,AllocationType.Commit,MemoryProtection.ReadWrite);
180
+
181
+
182
+
183
+ // LVITEM構造体を挿入するには、ポインターからポインターへのコピーを実行するWriteProcessMemoryAPIを使用する必要があります。したがって、マネージLVITEM構造をアンマネージLVITEMポインターに変換する必要があります
184
+
185
+ //最初にアンマネージメモリの一部を割り当てます。
186
+
187
+
188
+
189
+ var lvItemLocalPtr = Marshal.AllocHGlobal(lvItemSize);
190
+
191
+
192
+
193
+ //管理対象オブジェクトを管理対象外メモリにコピーします
194
+
195
+ Marshal.StructureToPtr(lvItem, lvItemLocalPtr, false);
196
+
197
+
198
+
199
+ int NumberOfBytesRead = 0;
200
+
201
+
202
+
203
+ //リモートプロセスのメモリに書き込みます
204
+
205
+ WriteProcessMemory(hProcess, lvItemBufferPtr,lvItemLocalPtr,(uint)lvItemSize,out NumberOfBytesRead) ;
206
+
207
+
208
+
209
+ //リストビューに、必要なテキストを入力するように指示します
210
+
211
+ SendMessage(hWnd, LVM_GETITEMTEXT, itemId, lvItemBufferPtr);
212
+
213
+
214
+
215
+ //テキストを読む。 CLRはポインタとバイト配列の間でマーシャリングする方法を知っているため、
216
+
217
+ //AllocHGlobalの代わりに、取得したテキストを格納するためにマネージバイト配列を割り当てます。
218
+
219
+ var localTextBuffer = new byte[MAX_GETITEMTEXT_LENGTH];
220
+
221
+ IntPtr ptrNumberOfBytesRead = IntPtr.Zero;
222
+
223
+ ReadProcessMemory(hProcess,textBufferPtr,localTextBuffer,(int)MAX_LVMSTRING, out ptrNumberOfBytesRead);
224
+
225
+
226
+
227
+ //バイト配列を文字列に変換します。リモートプロセスがUnicodeを使用すると仮定します
228
+
229
+ var text = Encoding.Unicode.GetString(localTextBuffer);
230
+
231
+ //末尾のゼロは自動的にクリアされません
232
+
233
+ text = text.Substring(0, text.IndexOf('\0'));
234
+
235
+
236
+
237
+ //最後に、割り当てたすべてのメモリを解放し、開いたプロセスハンドルを閉じます
238
+
239
+ VirtualFreeEx(hProcess, textBufferPtr, 0, AllocationType.Release);
240
+
241
+ VirtualFreeEx(hProcess, lvItemBufferPtr, 0, AllocationType.Release);
242
+
243
+ Marshal.FreeHGlobal(lvItemLocalPtr);
244
+
245
+
135
246
  ```
136
247
 
137
248
 
249
+
250
+
138
251
  ### 試したこと
139
252
 
140
253
  SendMessageの第4引数をIntPtr型や構造体そのものを入れてみたりしましたが、どれも同じく相手側が落ちてしまうという結果になりました。