C語言如何執行buf中的代碼?

能在 buf中寫一段代碼,讓程序執行么,比如

char szBuf[1024]={0};

strcpy(szBuf, "stricmp("1","2");");

怎麼調用 szBuf ,才能實現和下面一樣的效果

int k = stricmp("1","2");

可以計算出表達式


首先你的內存要有可執行許可權,然後你把一個函數的機器碼完整地寫進去,最後把這個內存強制轉換成一個函數指針就可以執行了。至於參數和結果是如何被彙編語言訪問的,這跟你使用什麼編譯器、以及函數指針類型的calling convention都有關係,你需要了解這所有的細節。

VirtualProtect function (Windows)

Memory Protection Constants (Windows)

PAGE_EXECUTE

http://www.cppblog.com/vczh/archive/2009/02/22/74622.html


strcpy(szBuf, "stricmp("1","2");");

這裡的szBuf只是保存了字元串值而已,並不是可執行的代碼,從代碼到可執行的二進位指令需要編譯,亦或者通過解釋執行.需要調用C編譯器或解釋器.

若要直接執行Buffer裡面的代碼必須是二進位指令.

這裡提供一種可直接執行題主給的stricmp的例子:

x86

char szBuf[] = "x8bx44x24x04x8bx5cx24x08x0fxbex08x85xc9x74x0fx0fxbex13x85xd2x74x08x3bxcax75x04x40x43xebxeax0fxbex08x0fxbex13x2bxcax8bxc1xc3";

調用:

int(*_stricmp)(char[], char[]) = (int(*)(char[], char[]))szBuf;
printf("%d",_stricmp("str1", "str2"));

前提是szBuf的內存為可執行,Windows下使用VirtualProtectEx修改,Linux下使用mmap修改該內存位置為可執行.

Windows下的例子:

#include &
#include &

char szBuf[] = "x8bx44x24x04x8bx5cx24x08x0fxbex08x85xc9x74x0fx0fxbex13x85xd2x74x08x3bxcax75x04x40x43xebxeax0fxbex08x0fxbex13x2bxcax8bxc1xc3";

int main()
{
int(*_stricmp)(char[], char[]) = (int(*)(char[], char[]))szBuf;

DWORD OldProtect;
VirtualProtectEx(GetCurrentProcess(),
szBuf, sizeof(szBuf),
PAGE_EXECUTE_READWRITE,
OldProtect);

printf("%d",_stricmp("str1", "str2"));

VirtualProtectEx(GetCurrentProcess(),
szBuf, sizeof(szBuf),
OldProtect,
NULL);

return 0;
}

szBuf里的代碼對應的彙編如下:

mov eax, [esp+0x04]
mov ebx, [esp+0x08]

__loop :
movsx ecx, byte ptr[eax]
test ecx, ecx
je __exit
movsx edx, byte ptr[ebx]
test edx, edx
je __exit

cmp ecx, edx
jne __exit

inc eax
inc ebx
jmp __loop

__exit :
movsx ecx, byte ptr [eax]
movsx edx, byte ptr [ebx]
sub ecx, edx
mov eax, ecx
ret


LZ可以下載一下tcc的源碼,它有這種on the fly的執行方式的。

如果出現不可執行錯誤(像輪子哥提到的那樣),就VirtualProtect一下。


先用這個VirtualProtect函數,這個函數會改變段描述符裡面的屬性,這樣把棧變成可執行的。然後char shellcode[]="反彙編機器碼";

_asm

{push shellcode

ret

}


謝邀,題主你要的是直接執行源碼,相當於要有一個C的eval函數。

有一個簡單的版本可以參考:rswier/c4 · GitHub


我覺得無法實現,

除非程序自帶c語言解釋器,

或者給編譯器加上這個功能,


首先~你得先實現一個簡單的c語言解釋器,將你寫入buffer的字元串解釋成彙編位元組碼,而恰好你這內存要擁有可執行許可權,請參考輪子哥答案,再,要用到api的話,要修復程序偏移,也就是重定位能識別到api地址,這個可以參考shellcode技術。

其實現在有一個挺好的東西,就是tiny c的實現,可以buffer執行代碼,當然,要是Windows api,貌似tiny c沒做支持。


bufferoverflow shellcode


把字元串寫到文件里,然後用解釋器行不?


雙引號裡面的字元串常量,需要先編譯成機器能看懂的二進位碼吧??


題主的問題讓我想起了緩衝區溢出攻擊


這不就是shellcode么,知道shellcode怎麼寫,就明白了。手機碼字,看個意思就好:

char buf[] = "xxxx";

typedef int (func_t*)(const char*, const char*);

func_t f = (func_t)(long)buf;

int rv = (*f)(str1, str2);

至於buf裡頭的東西,用對應的機器碼填充即可。

當然數據段可能不能執行,有些編譯選項需要調一下,或者自己改變可執行的屬性。


可以參考ATL的Thunk實現,必須調用操作系統提供的API,和語言無關。


推薦閱讀:

怎樣才是一個基本水平的c++程序員?
C++11中用{}初始化,有等於號和沒等於號的區別是什麼?
聲明多個指針時,為什麼實際只有第一個是指針?
cpp 如何 debug memory leak?
C++中類的構造函數,成員變數是在初始化列表初始化還是在函數體中進行賦值?

TAG:編程語言 | C編程語言 | C | 編譯原理 | 程序優化 |