ダメ関数潰し

個人的にはシンボルがそのままな限り動くLD_PRELOADで対応したいところだが、
ローカル関数やアドレス指定で直接呼び出されている関数にはPLT経由で制御を奪う方法は
使えない。


本番用の弄るのはアレなので、適当にサンプルをでっち上げて練習してみるテスト。
(ソースあればこんな事しなくても済むというのは以下略)


てきとーなダメサンプル。無駄な物色々入っているけど気にしない。

int main(int argc,char ** argv){
        int a=1, b=2;
        int ret;
        char buff[128];
        ret = func1(a,1,a);
        ret = func2(a,NULL,b);
        printf("%d\n",ret);
        return 0;
}
int func1(int a,int b,int c){
        char buff[256];
        int ret;
        ret = a * 2 + c;
        return ret;
}
int func2(int a,char *b,int c){
        sprintf(b,"%d %d",a,c);
        return 0;
}

対象のdisassemble結果はこんなの。sprintfがNULL書き込みで死亡する。

08048587 <func2>:
 8048587:       55                      push   %ebp
 8048588:       89 e5                   mov    %esp,%ebp
 804858a:       53                      push   %ebx
 804858b:       83 ec 14                sub    $0x14,%esp
 804858e:       e8 34 00 00 00          call   80485c7 <__i686.get_pc_thunk.bx>
 8048593:       81 c3 85 12 00 00       add    $0x1285,%ebx
 8048599:       8b 45 10                mov    0x10(%ebp),%eax
 804859c:       89 44 24 0c             mov    %eax,0xc(%esp)
 80485a0:       8b 45 08                mov    0x8(%ebp),%eax
 80485a3:       89 44 24 08             mov    %eax,0x8(%esp)
 80485a7:       8d 83 0c ef ff ff       lea    0xffffef0c(%ebx),%eax
 80485ad:       89 44 24 04             mov    %eax,0x4(%esp)
 80485b1:       8b 45 0c                mov    0xc(%ebp),%eax
 80485b4:       89 04 24                mov    %eax,(%esp)
 80485b7:       e8 c4 fd ff ff          call   8048380 <sprintf@plt>
 80485bc:       b8 00 00 00 00          mov    $0x0,%eax
 80485c1:       83 c4 14                add    $0x14,%esp
 80485c4:       5b                      pop    %ebx
 80485c5:       5d                      pop    %ebp
 80485c6:       c3                      ret

1. 該当箇所をnopでつぶす
ある意味常套手段。そのまま滑っていく。

 - 80485b7:       e8 c4 fd ff ff          call   8048380 <sprintf@plt>
 + 80485b7:       90                      nop
 + 80485b8:       90                      nop
 + 80485b9:       90                      nop
 + 80485ba:       90                      nop
 + 80485bb:       90                      nop

2. 無理矢理returnする
nopで滑っていってその後の処理に当たるのが嫌な場合はこっち。
スタック弄ってる場合はretする前に戻す必要あるので注意。(この場合は%ebxと%ebp)
戻り値書きたい場合は数バイト確保して%eaxとかにmovして積む。

 - 804858e:       e8 34 00 00 00          call   80485c7 <__i686.get_pc_thunk.bx>
 - 8048593:       81 c3 85 12 00 00       add    $0x1285,%ebx
 + 804858e:       b8 01 00 00 00          mov    $0x1,%eax
 + 8048593:       83 c4 14                add    $0x14,%esp
 + 8048596:       5b                      pop    %ebx
 + 8048597:       5d                      pop    %ebp
 + 8048598:       c3                      ret

全く呼び出される必要がない場合は呼び出しもとを潰せばOK。
callは5byteなので、ちょうど%eaxにmovできる為リターンコードも制御可能。