アカウント名:
パスワード:
>・プログラムの自己書き換え。
いや、普通にできますけど?もしこれができなくなっているなら、脆弱性の問題で苦労したりしませんって。
>・例えばBASICで、まとまったひとつのプログラムの冒頭に
いや、普通にできますけど?最近は肥大化したフレームワークの底に隠されてしまう傾向にありますけど、フレームワークをつかわなければ普通にできますよ。
>・プログラムの自己書き換え。 いや、普通にできますけど? もしこれができなくなっているなら、脆弱性の問題で苦労したりしませんって。
ネイティブなコードを吐き出すコンパイラで作ったプログラムを最近のCPU/OS上で動かすと, 大抵の場合メモリ保護機能に引っかかってsegmentation violation例外なんかを起こすと思いますが. もちろん
あたりは話が別になりますが.
それこそ, 低レベルな記述のできるC言語あたりを使って, 関数へのポインタを適当なデータへのポインタにキャストして, データを代入してみれば実験できるでしょう. 例えば
#include <stdio.h> void dummy(){ return;} main(int argc, char **argv){ void (*ptr)(); char *writable; ptr = dummy; writable = (char *)ptr; writable[0] = '\0';}
なんてプログラムをコンパイルして, もしも問題なく実行できちゃうのであれば, 動的コード書き換えによる脆弱性を注意しないといけないですね.(FreeBSD amd64の上で動かすと, ちゃんとSIGSEGVで落ちます)
多分, 今, 組み込みとか以外の環境で自己書き換えみたいなことが必要ならば, lambdaとかの動的関数生成を使うほうがスマートなんじゃないかと思います.
その前にmprotect()とか追加するだけで普通に動くでしょ。メモリ保護のほうが後付けでデータをプログラムとして解釈できるというフォン・ノイマン型コンピュータの原則は動きませんよ。
普通かどうかはともかくLinux Kernelのftraceのフックの仕込みがこれ系(であってるよね?)ですね。カーネル内部はいろいろアレなことするんじゃないかなぁ。
# ref:# 10月版 2.6.27はLTSに、命名規則の変更案も飛び出した(1/2) - @IT [atmarkit.co.jp]# トレーサ関連に大きな進展、ftraceがデファクトに?(1/2) - @IT [atmarkit.co.jp]
そこで、ftraceの主要機能の1つとして、事前に全関数の先頭に5バイトのNOPを挿入しておき、関数トレースモードをONにしたときのみ、プロファイラ関数呼び出しが動的パッチングにより生成されるという機能がありました(x86においてはjmp命令が5バイトです。
DEP ONにしろよ...
DEP有っても上手く壊して実行可能属性が付けられたり落とし忘れが有ったら無力かと
>上手く壊して関数ポインタをVirtualAllocなどに書き換えて云々
「出来なくなった」ではなく「やらなくなった(やる必要がなくなった)」ってことでは?
組み込み系では今でも現役の手法なのかも知れないけど、潤沢にメモりが使える昨今、自己書き換えで数バイトの節約なんてみみっちいことするより他に労力を割くほうがよほど生産性上がるし。
1命令の単位くらいの自己書き換えは、今も昔もトリッキーなテクニックだったでしょうけど。
OSがプログラムをロードするってのは、粒度が非常に大きい自己書き換えともいえるわけで、組み込み形でもOSとアプリを同時に変更・開発するような場合は自己書き換えは現役といえると思いますよ。
>・プログラムの自己書き換え。いや、普通にできますけど?もしこれができなくなっているなら、脆弱性の問題で苦労したりしませんって。
脆弱性って逆じゃないかい?大抵は実行属性の付いたセグメントは書き換え禁止で、書き換え可能なセグメントは実行禁止になってるはずだし。(DEP等が無いとそのまま通る環境が存在するのは虚しい限りだが)
意図的に実行可能+書き換え可能にしない限り、現代のOSでは本来自己書き換え出来てはだめです。
・・・まぁ、APIで書き換えれば無視出来る訳ですが。# Windowsで自プロセスにWriteProcessMemoryとか本末転倒なようで案外有効
まったくですな。必要なら都度VirtualProtectまたはmprotectで書込属性を与えて、書いて、書込権限剥奪・実行権限付与ですね。
自己書き換えはやらなくなったとしても、JITがはやっているので、広い意味で実行時にコードを書くという処理はちっとも廃れていないと思うのです。
> Windowsで自プロセスにWriteProcessMemoryとか本末転倒なようで案外有効昔、対象アプリの使ってるWSOCK32情報がでるツールがあってどうやってるんだろうと思って解析したら、DLLを横取りしてるんだけど動的ダイナミックリンクの場合は、DLLをすり替えてるだけだったんだけど、静的ダイナミックリンクは、コールかジャンプか忘れたけど呼び出すコードを全部書き換えてるのを思い出した。(対象が他プロセスなので、フック関数でそのプロセスに実行させてた。)当時、簡単にわかるAPIがないことがわかり残念に思った。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
弘法筆を選ばず、アレゲはキーボードを選ぶ -- アレゲ研究家
あれこれ (スコア:0)
類似のことで、例えばゲームで自分の残り機数データの格納アドレスを解析して、ミスしても減らないようにするとか。
・例えばBASICで、まとまったひとつのプログラムの冒頭に
FOR A=1 TO 100
末尾に
NEXT A
と付け加えるだけで繰り返し100回にできる、とか(今のWindowsだとVBscriptで出来るのか?やり方よくわからん)。
Re:あれこれ (スコア:1)
>・プログラムの自己書き換え。
いや、普通にできますけど?
もしこれができなくなっているなら、脆弱性の問題で苦労したりしませんって。
>・例えばBASICで、まとまったひとつのプログラムの冒頭に
いや、普通にできますけど?
最近は肥大化したフレームワークの底に隠されてしまう傾向にありますけど、フレームワークをつかわなければ普通にできますよ。
Re:あれこれ (スコア:1)
ネイティブなコードを吐き出すコンパイラで作ったプログラムを最近のCPU/OS上で動かすと, 大抵の場合メモリ保護機能に引っかかってsegmentation violation例外なんかを起こすと思いますが. もちろん
あたりは話が別になりますが.
それこそ, 低レベルな記述のできるC言語あたりを使って, 関数へのポインタを適当なデータへのポインタにキャストして, データを代入してみれば実験できるでしょう. 例えば
なんてプログラムをコンパイルして, もしも問題なく実行できちゃうのであれば, 動的コード書き換えによる脆弱性を注意しないといけないですね.(FreeBSD amd64の上で動かすと, ちゃんとSIGSEGVで落ちます)
多分, 今, 組み込みとか以外の環境で自己書き換えみたいなことが必要ならば, lambdaとかの動的関数生成を使うほうがスマートなんじゃないかと思います.
Re: (スコア:0)
その前にmprotect()とか追加するだけで普通に動くでしょ。
メモリ保護のほうが後付けでデータをプログラムとして解釈できるというフォン・ノイマン型コンピュータの原則は動きませんよ。
Re:あれこれ (スコア:1)
普通かどうかはともかくLinux Kernelのftraceのフックの仕込みがこれ系(であってるよね?)ですね。
カーネル内部はいろいろアレなことするんじゃないかなぁ。
# ref:
# 10月版 2.6.27はLTSに、命名規則の変更案も飛び出した(1/2) - @IT [atmarkit.co.jp]
# トレーサ関連に大きな進展、ftraceがデファクトに?(1/2) - @IT [atmarkit.co.jp]
M-FalconSky (暑いか寒い)
Re: (スコア:0)
DEP ONにしろよ...
Re: (スコア:0)
DEP有っても上手く壊して実行可能属性が付けられたり落とし忘れが有ったら無力かと
Re: (スコア:0)
>上手く壊して
関数ポインタをVirtualAllocなどに書き換えて云々
Re: (スコア:0)
「出来なくなった」ではなく「やらなくなった(やる必要がなくなった)」ってことでは?
組み込み系では今でも現役の手法なのかも知れないけど、潤沢にメモりが使える昨今、
自己書き換えで数バイトの節約なんてみみっちいことするより他に労力を割くほうが
よほど生産性上がるし。
Re:あれこれ (スコア:1)
1命令の単位くらいの自己書き換えは、今も昔もトリッキーなテクニックだったでしょうけど。
OSがプログラムをロードするってのは、粒度が非常に大きい自己書き換えともいえるわけで、組み込み形でもOSとアプリを同時に変更・開発するような場合は自己書き換えは現役といえると思いますよ。
Re:あれこれ (スコア:1)
Re: (スコア:0)
>・プログラムの自己書き換え。
いや、普通にできますけど?
もしこれができなくなっているなら、脆弱性の問題で苦労したりしませんって。
脆弱性って逆じゃないかい?
大抵は実行属性の付いたセグメントは書き換え禁止で、書き換え可能なセグメントは実行禁止になってるはずだし。(DEP等が無いとそのまま通る環境が存在するのは虚しい限りだが)
意図的に実行可能+書き換え可能にしない限り、現代のOSでは本来自己書き換え出来てはだめです。
・・・まぁ、APIで書き換えれば無視出来る訳ですが。
# Windowsで自プロセスにWriteProcessMemoryとか本末転倒なようで案外有効
Re: (スコア:0)
まったくですな。必要なら都度VirtualProtectまたはmprotectで書込属性を与えて、書いて、書込権限剥奪・実行権限付与ですね。
自己書き換えはやらなくなったとしても、JITがはやっているので、広い意味で実行時にコードを書くという処理はちっとも廃れていないと思うのです。
Re: (スコア:0)
> Windowsで自プロセスにWriteProcessMemoryとか本末転倒なようで案外有効
昔、対象アプリの使ってるWSOCK32情報がでるツールがあってどうやってるんだろうと思って
解析したら、DLLを横取りしてるんだけど動的ダイナミックリンクの場合は、
DLLをすり替えてるだけだったんだけど、静的ダイナミックリンクは、
コールかジャンプか忘れたけど呼び出すコードを全部書き換えてるのを思い出した。
(対象が他プロセスなので、フック関数でそのプロセスに実行させてた。)
当時、簡単にわかるAPIがないことがわかり残念に思った。