之前已經知道了函數這個玩意在計算機中的本質,本身在棧中存放其實就是一個指針的方式,而指針指向的內容就是在內存中存放的機器碼。


解釋到這裡就已經很明顯了,函數其實並不是一定要在編譯期載入內存後靜態,也就是固定的方式運行的。

我們可以手動開闢內存,輸入機器碼,然後讓指針指向這塊內存。從而實現在運行時動態生成函數。

哦呼~想想就有點激動,這個邏輯其實就有點像動態語言,例如PHP,JAVA,Python的解釋器的工作方式。

而且這個方式可以不用在語言中編寫彙編,可以繞過某些平臺無法在C中編寫彙編的限制。

首先我們得獲取機器碼,我這裡直接通過反彙編直接獲取。

1//0x00005555555547a7 <+0>:	55                 	push   rbp
2//0x00005555555547a8 <+1>:	48 89 e5           	mov    rbp,rsp
3//0x00005555555547ab <+4>:	b8 01 00 00 00     	mov    eax,0x1
4//0x00005555555547b0 <+9>:	5d                 	pop    rbp
5//0x00005555555547b1 <+10>:	c3                 	ret
6int ret() {
7    return 1;
8}

然後把這些機器碼寫進內存, 之後進行類型強轉之後,就可以直接運行。

 1char ret_code[] = {
 2            0x55,
 3            0x48, 0x89, 0xe5,
 4            0xb8, 0x10, 0x00, 0x00, 0x00,
 5            0x5d,
 6            0xc3
 7    };
 8
 9    void *tmp = mmap(
10            NULL,
11            getpagesize(),
12            PROT_READ | PROT_WRITE | PROT_EXEC,
13            MAP_ANONYMOUS | MAP_PRIVATE,
14            -1,
15            0
16            );
17
18    memscp3(tmp, ret_code, sizeof(ret_code));
19
20    ret_p p = tmp;
21
22    int bbb = p();
23
24    printf("%d\n", bbb);