質問編集履歴

1

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

2021/09/16 13:27

投稿

shinyama
shinyama

スコア1

test CHANGED
File without changes
test CHANGED
@@ -250,26 +250,252 @@
250
250
 
251
251
 
252
252
 
253
-
254
-
255
-   
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
-
264
-
265
-
266
-
267
-
268
-
269
253
  ```
270
254
 
271
255
 
272
256
 
257
+ ###9/16修正後
258
+
259
+ ソフトが落ちることはなくなりましたが、textの中身は””状態で取得することができませんでした。。
260
+
261
+ 構造体はすべてintに変更しています
262
+
263
+ 〇主コード抜粋
264
+
265
+ ```
266
+
267
+ //listViewのプロセスIDを取得する
268
+
269
+
270
+
271
+ int dwProcessId;
272
+
273
+
274
+
275
+ GetWindowThreadProcessId(hWnd, out dwProcessId);
276
+
277
+
278
+
279
+ // 取得したプロセスIDをオープンする
280
+
281
+
282
+
283
+ IntPtr hProcess;
284
+
285
+
286
+
287
+ hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, (uint)dwProcessId);
288
+
289
+
290
+
291
+ //必要なリストビューアイテムのテキストを格納するために、文字列にバッファを割り当て
292
+
293
+
294
+
295
+ var textBufferPtr = VirtualAllocEx(hProcess, IntPtr.Zero,MAX_LVMSTRING,AllocationType.Commit, MemoryProtection.ReadWrite);
296
+
297
+
298
+
299
+
300
+
301
+ //listViewの行数
302
+
303
+
304
+
305
+ int itemId = 2;
306
+
307
+
308
+
309
+ //listViewの列数
310
+
311
+
312
+
313
+ int subItemId = 2;
314
+
315
+
316
+
317
+
318
+
319
+
320
+
321
+ //構造体のnew
322
+
323
+
324
+
325
+ tagLVITEMA lvItem = new tagLVITEMA();
326
+
327
+
328
+
329
+ lvItem.mask = LVIF_TEXT;
330
+
331
+
332
+
333
+ lvItem.cchTextMax = (int)MAX_LVMSTRING;
334
+
335
+
336
+
337
+ lvItem.iItem = itemId;
338
+
339
+
340
+
341
+ lvItem.iSubItem = subItemId;
342
+
343
+
344
+
345
+
346
+
347
+
348
+
349
+ //リモートプロセスでLVITEM構造にメモリを割り当て
350
+
351
+
352
+
353
+ int lvItemSize = Marshal.SizeOf(lvItem);
354
+
355
+
356
+
357
+ var lvItemBufferPtr = VirtualAllocEx(hProcess, IntPtr.Zero,(uint)lvItemSize,AllocationType.Commit,MemoryProtection.ReadWrite);
358
+
359
+
360
+
361
+
362
+
363
+
364
+
365
+ // LVITEM構造体を挿入するには、ポインターからポインターへのコピーを実行するWriteProcessMemoryAPIを使用する必要があります。したがって、マネージLVITEM構造をアンマネージLVITEMポインターに変換する必要があります
366
+
367
+
368
+
369
+ //最初にアンマネージメモリの一部を割り当てます。
370
+
371
+
372
+
373
+
374
+
375
+
376
+
377
+ var lvItemLocalPtr = Marshal.AllocHGlobal(lvItemSize);
378
+
379
+
380
+
381
+
382
+
383
+
384
+
385
+ //管理対象オブジェクトを管理対象外メモリにコピーします
386
+
387
+
388
+
389
+ Marshal.StructureToPtr(lvItem, lvItemLocalPtr, false);
390
+
391
+
392
+
393
+
394
+
395
+
396
+
397
+ int NumberOfBytesRead = 0;
398
+
399
+
400
+
401
+
402
+
403
+
404
+
405
+ //リモートプロセスのメモリに書き込みます
406
+
407
+
408
+
409
+ WriteProcessMemory(hProcess, lvItemBufferPtr,lvItemLocalPtr,(uint)lvItemSize,out NumberOfBytesRead) ;
410
+
411
+
412
+
413
+
414
+
415
+
416
+
417
+ //リストビューに、必要なテキストを入力するように指示します
418
+
419
+
420
+
421
+ SendMessage(hWnd, LVM_GETITEMTEXT, itemId, lvItemBufferPtr);
422
+
423
+
424
+
425
+
426
+
427
+
428
+
429
+ //テキストを読む。 CLRはポインタとバイト配列の間でマーシャリングする方法を知っているため、
430
+
431
+
432
+
433
+ //AllocHGlobalの代わりに、取得したテキストを格納するためにマネージバイト配列を割り当てます。
434
+
435
+
436
+
437
+ var localTextBuffer = new byte[MAX_GETITEMTEXT_LENGTH];
438
+
439
+
440
+
441
+ IntPtr ptrNumberOfBytesRead = IntPtr.Zero;
442
+
443
+
444
+
445
+ ReadProcessMemory(hProcess,textBufferPtr,localTextBuffer,(int)MAX_LVMSTRING, out ptrNumberOfBytesRead);
446
+
447
+
448
+
449
+
450
+
451
+
452
+
453
+ //バイト配列を文字列に変換します。リモートプロセスがUnicodeを使用すると仮定します
454
+
455
+
456
+
457
+ var text = Encoding.Unicode.GetString(localTextBuffer);
458
+
459
+
460
+
461
+ //末尾のゼロは自動的にクリアされません
462
+
463
+
464
+
465
+ text = text.Substring(0, text.IndexOf('\0'));
466
+
467
+
468
+
469
+
470
+
471
+
472
+
473
+ //最後に、割り当てたすべてのメモリを解放し、開いたプロセスハンドルを閉じます
474
+
475
+
476
+
477
+ VirtualFreeEx(hProcess, textBufferPtr, 0, AllocationType.Release);
478
+
479
+
480
+
481
+ VirtualFreeEx(hProcess, lvItemBufferPtr, 0, AllocationType.Release);
482
+
483
+
484
+
485
+ Marshal.FreeHGlobal(lvItemLocalPtr);
486
+
487
+
488
+
489
+
490
+
491
+ ```
492
+
493
+
494
+
495
+
496
+
497
+
498
+
273
499
 
274
500
 
275
501
  ### 試したこと