1. 程式人生 > >隨想錄(systemtap中的基本原理)

隨想錄(systemtap中的基本原理)

【 宣告:版權所有,歡迎轉載,請勿用於商業用途。  聯絡信箱:feixiaoxing @163.com】

    systemtap中的probe功能非常令人著迷。這種類似hook的方法對於我們除錯效能和分析問題非常有用,更重要的是它還不需要重新編譯,僅僅依靠幾個指令碼就可以完成你想要的功能,這不得不說是非常神奇

    後來,我自己想了一下,這個功能應該不是很複雜。關鍵就是要做好probe函式的保護和恢復工作就可以了。想到這,我就在vc 6.0上模擬實現了這麼一段程式碼來說明問題。注意,如果在vs2010上執行,恢復地址那一行程式碼修改為*(&data +3)=test即可。

#include <stdio.h>
#include <windows.h>

#define LEN 8
unsigned char save[LEN];

void test();
void stub();

// replace function
void stub()
{
	unsigned int data;
	unsigned char* p;
	unsigned int index;

	p = test;

	// above is data, ebp and return address
	// restore return address
	*(&data + 2) = test;

	// restore data
	for(index = 0; index < LEN; index ++) {
		p[index] = save[index];
	}

	printf("stub ");
}

//original function

void test()
{
	printf(" china");
}

// content add is as follows
//	__asm {	
//		lea eax, stub
//		call eax
//	}

void set_stub(unsigned char* p, unsigned int data)
{	

	*(unsigned short*)p = 0x058d;
	*(unsigned int*)(p+2) = data;
	*(unsigned short*)(p+6) = 0xd0ff;
}

int main()
{
	unsigned char* p = (unsigned char*) test;
	DWORD old;
	DWORD tmp;
	unsigned index;

	// modify attribute of code segment
	if(!VirtualProtect(p, LEN, 0x40, &old)){
		exit(1);
	}
	
	for(index = 0; index < LEN; index ++){
		save[index] = p[index];
	}

	// modify address
 	set_stub(p, stub);

	// run test function
	test();

	// restore attribute of code segment
	if(!VirtualProtect(p, LEN, old, &tmp)){
		exit(1);
	}

	return 1;
}

    這段程式碼的內容不復雜,關鍵就是說強迫執行test函式之前一定要執行一下stub函式。首先,我們需要將test函式開始的程式碼設定成可讀可寫的屬性;其次就是儲存這一段原始程式碼內容,因為之後還是需要恢復的;接著利用set_stub函式將test一開始的程式碼設定成一段跳轉內容,這樣可以直接到stub執行;後面stub執行的時候,恢復ret地址和test開始處的data,這樣在stub返回的時候可以繼續到test函式執行;當然最後所有工作都完成的時候就可以恢復test資料段的屬性了。就是這麼簡單。