数日前、単一の呼び出し命令にパッチを当てて簡単なフック/迂回路を書きました。Ubuntu 12.xyz (32 ビット) で動作しましたが、Linux Mint 17.1 (32 ビット) に更新すると、セグメンテーション エラーが発生します。
私は2つのプロジェクトを持っています
- goodGuy という名前の関数を呼び出すターゲット プロジェクト
- ターゲット アプリケーションの呼び出し命令からのオフセットを上書きする dlopen() によってロードされたライブラリ プロジェクト
呼び出し命令のオフセットを上書きする前に、ページの保護を次のように変更します。
mprotect(pageOf(address),pagesize,PROT_WRITE|PROT_EXEC|PROT_READ)
これは正常に機能します (0 を返します)。
プログラムをデバッグすると、呼び出しのアドレスに書き込もうとしてクラッシュします。
memcpy((void*)(address + 1),(void*)&callOffset,4);
命令を上書きすることは許可されていないようですが、なぜですか?
ALSR を無効に-z execstack -fno-stack-protector
し、g++ でフラグを使用しました。
私のアプリケーションが命令を書くことを許可する方法を知っていますか?
ありがとう、アレックス
編集
申し訳ありませんが、コードは次のとおりです。
対象アプリケーション:
#include <dlfcn.h>
#include <stdio.h>
#include <stdio.h>
#include <iostream>
void goodGuy();
//full lib path !
char libPath[] = "INSER_YOUR_PATH_HERE/lib.so";
int main(){
dlopen(libPath,RTLD_NOW);
goodGuy();
return 0;
}
void goodGuy(){
printf("good guy :)\n");
}
および共有ライブラリ コード:
#include <stdio.h>
#include <cstring>
#include <stdint.h>
#include <sys/mman.h>
#include <unistd.h>
void badGuy();
int pagesize = sysconf(_SC_PAGESIZE);
void *pageOf(void* p){
return (void*)((unsigned int)p & ~(pagesize - 1));
}
extern "C" void __attribute__ ((constructor)) DllLoad(void){
uint32_t addressOfCall = 0x0804862a; //Address where goodGuy is called in target app
uint32_t addressOfNextInstruction = addressOfCall + 5;
uint32_t callOffset = (uint32_t)badGuy - addressOfNextInstruction;
mprotect(pageOf((void*)(addressOfCall + 1)),pagesize, PROT_WRITE|PROT_EXEC|PROT_READ);
memcpy((void*)(addressOfCall + 1),(void*)&callOffset,4);
}
void badGuy(){
printf("bad guy :(\n");
}
addressOfCall を見つけるには、gdb でターゲット アプリケーションを開き、gdb target
main 関数を表示しdisas main
て、+29
gdb$ disas main
Dump of assembler code for function main()
0x0804860d <+0>: push ebp
0x0804860e <+1>: mov ebp,esp
0x08048610 <+3>: and esp,0xfffffff0
0x08048613 <+6>: sub esp,0x10
0x08048616 <+9>: mov DWORD PTR [esp+0x4],0x2
0x0804861e <+17>: mov DWORD PTR [esp],0x804a060
0x08048625 <+24>: call 0x80484f0 <dlopen@plt>
___________
|0x0804862a| <+29>: call 0x8048636 <goodGuy()>
|__________|
0x0804862f <+34>: mov eax,0x0
0x08048634 <+39>: leave
0x08048635 <+40>: ret