今仕事でVC++の6.0を使用しております、一つとても困っていることがあります。
それは変数へのアドレスアクセス(ポインタアクセス)です。
VCでコンパイルすると、グローバル変数はMapFileに
0003:00000d88 _count3 1008fd88 main.obj
↑defalutの配置は0x100000000からなのでそれを
示しているのでしょうか?
とかって表示されます。
でも実際にVCのデバッカで動作させると 0x45E00fd88 にcount3の変数は割り当てられ
てます。
このcount3変数にアドレス情報だけでアクセスしたいのですが、どうすればよろしい
でしょうか?
MapFileのアドレス情報+アプリケーション実行時のアドレスOffsetでアクセスできる
と考えているのですが、そのアプリ実行時のベースとなるアドレスが解りません。
これを求めるWinApi等ありますでしょうか?
ご存じであれば教えてください。
以上、宜しくお願いいたします。
なにがしたいのかいまいちわかりませんが、
当該プログラムの中からポインタを取得するなら &count3 だけです。
当該プログラムの外から count3 を書き換えようという魂胆?
tetrapodさんへ
はい。
その通りです。
プログラム外よりアドレス情報+型情報をもらって、内容を書き換えたいと思っております。
アドレス情報はMAPファイルから取得する予定です。
もーり
Win32 ではメモリ空間はプロセスごとに保護されているのを承知の上でやりたいのですね?
OS が用意してくれているセキュリティを無視して強引な書き換えをしたいのですね。
とりあえず WriteProcessMemory や OpenProcess など参照。
対象アプリのソースを変更できるようなら WM_COPYDATA とかで可能かも。
MSDN Platform SDK Documents 中の Interprocess Communications など参照。
Win32 は仮想記憶で動いているという事はご存知ですか?そして、各プログラム(タスク)は
別々の記憶空間をOSが割り当てて動いていることもご存知ですか?
その為、別のアプリ B が、アプリ A の番地に直接触る事は(不可能とは言わないけれども、
動作中のアプリ A の特定の変数の番地を取得したぐらいでは)出来ないと思います
勿論、起動前の A.EXE の特定の位置の値をファイルのデーターとして変更しておいて A を
起動するという技は使えるかもしれませんが、チェックサムまで書き換えなければならず
面倒な事になると思います
tetrapodさん、島さん
アドバイスありがとうございます。
私の説明が悪く申し訳ございません。
再度説明させてください。
プログラムAから別のプログラムBの変数を書き換えたいのですが、直接ではなくメッセージ等を
使って書き換えたい変数のアドレスと内容をプログラムAからBへ渡します。
渡されたBはそのアドレス(自分のグローバル変数)にポインタアクセスを行って値を書き換え
ます。ここで問題になるのは変数のアドレス情報なのですが、MAPファイルを作成すればそのプ
ログラム内で使用するアドレス情報が出来ます。(前記だと0x1008fd88番地)実際に動作する
場合にはtetrapodさん、島さんご指摘の通り仮想アドレス空間が割り当てられると思うのです
が、その場合でも仮想ベースアドレス+0x1008fd88=0x45E00fd88 この場合仮想ベースアド
レスは0x44DF80000?となるのでは。と考えております。
このときのプログラム実行時のベースアドレスを求める方法が知りたいのですが、解りません。
Windows初心者で申し訳ございません。
ご教授お願いいたします。
もーり
島 さん
>その為、別のアプリ B が、アプリ A の番地に直接触る事は(不可能とは言わないけれども、
>動作中のアプリ A の特定の変数の番地を取得したぐらいでは)出来ないと思います
ほぼ御意ですが、できないとデバッガが作れないです。
そのための Write/Read ProcessMemory です。
# 「直接」触ってはいない、という意味ではまさに御意。
もーり さん
ということであなたがやりたがっているのは、デバッガを作ることとほぼ同値です。
gdb のソースなど参照。
ちなみにプロセス毎の仮想メモリ空間中におけるプログラムのロードアドレスは、
リンク時に指定するものです。よってあなたがどのようにプログラムをリンクしたかで
ロードアドレスは変化します。デフォルトは 0x400000(EXE の場合) ですが。
リンカオプション /BASE の説明など参照。
でもふつー MAP ファイル中のアドレスってそのまま仮想記憶空間中のアドレス
なんですけどねー。ウチで作った簡単なテストプログラムではそうだった。
tetrapod さん
>ということであなたがやりたがっているのは、デバッガを作ることとほぼ同値です。
>gdb のソースなど参照。
うーん。そこまで大事とは考えていないのですが・・・・
>ちなみにプロセス毎の仮想メモリ空間中におけるプログラムのロードアドレスは、
>リンク時に指定するものです。よってあなたがどのようにプログラムをリンクしたかで
>ロードアドレスは変化します。デフォルトは 0x400000(EXE の場合) ですが。
>リンカオプション /BASE の説明など参照。
はい。一応見てはおりました。
/BASEでロードアドレスを指定することは出来ており、それを基準にアドレスを取得することは
可能なのですが、/BASE設定には但し書きがあり、設定したアドレス空間が取得できない場合は
別の空間に割り当てられると言うことです。
ですので、EXE(TASK)実行時にそのプログラムのベースアドレスを動的に取得できれば。と考
えておりました。静的に設定することは可能とは思いますがいちいち設定しなくてはいけないの
ともし取得できなかった場合の事を考えると静的設定は難しいと考えております。
もーり
>ほぼ御意ですが、できないとデバッガが作れないです。
>そのための Write/Read ProcessMemory です。
その辺(へん)も判った上での書き込みでしたが、余り厳密に書くと(書く前に再調査すべき
事柄があり(うろ覚えになっているものもあるので)、その意味では手抜きだった事は
認めますし、)長くなってしまうので、「不可能とは言わないけれども...」という表現に
したのです
> /BASE設定には但し書きがあり、設定したアドレス空間が取得できない場合は
> 別の空間に割り当てられると言うことです。
実際にロードされたアドレスを取得するには、GetModuleHandle(NULL)
とします。
これはWinMain()に渡されるhInstanceと同じ値を返します。
ところで、マルチポストはやめましょう。
http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?print+200307/03070003.txt
なんか入れ違っているうちにコメント増えてますが...
GetModuleHandle ではロードアドレスは取れないでしょう。
GetModuleInformation のような気がします。
# ってウチの VC6 には psapi.h/lib が無いんだけど...
# 最新 SDK が必要?
デバッガ作るほどの問題では確かに無いですね。
masaki さん
ありがとうございました。
おかげで解決できました。
>ところで、マルチポストはやめましょう。
> http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?print+200307/03070003.txt
すいません。
先に上記アドレスに質問したのですが、URLが解らなくなってしまい。
ここに再度質問いたしました。
上記アドレスの掲示板にも終了の旨、投稿いたします。
島さん、tetrapodさん
ご教授ありがとうございました。
今後の参考になりました。
以上、ありがとうございました。
もーり
tetrapodさん
GetModuleHandle(DLL名); //実はDLLを作成しておりました。
でDLLのロードアドレスが取得できました。
この値にMAPファイルのOFFSETを加えるとドンピシャグローバル変数のアドレスでした。
もーり