May 07, 2007

qsort 與 shellcode

瞥見某廠商寫的 driver,啟發我的靈感。Standard C Library 的 qsort 函式本身就是相當奇妙的設計,以下是其宣告:
void qsort(void *base, size_t nmemb, size_t size,
           int(*compar)(const void *, const void *));
吸引我的地方就是 callback function,用以作比較資料之用。探討與 shellcode 的關聯前,先來寫個簡單的範例程式:(qsort.c)
#include <stdlib.h>
#include <stdio.h>
 
static int cmp_func(int* a, int* b) {
        return (*a - *b);
}

int array[10] = { 5, 9, 2, 8, 1, 4, 7, 10, 3, 6 };
int main() {
        int i;
        qsort(array, 10, sizeof(array[0]), cmp_func);
        for (i = 0; i < 10; i++) {                                                                  
                printf("-> %d\n", array[i]);
        }
        return 0;
}
這個程式碼的輸出很容易想像,就是將 1, 2, 3, ..., 10 排序印列,那我們作點觀察:
$ gcc -Os -o qsort qsort.c 2>/dev/null
$ objdump -xd qsort | grep -A8 "<cmp_func>"
08048384 :
 8048384:	55                   	push   %ebp
 8048385:	89 e5                	mov    %esp,%ebp
 8048387:	8b 45 08             	mov    0x8(%ebp),%eax
 804838a:	8b 55 0c             	mov    0xc(%ebp),%edx
 804838d:	5d                   	pop    %ebp
 804838e:	8b 00                	mov    (%eax),%eax
 8048390:	2b 02                	sub    (%edx),%eax
 8048392:	c3                   	ret
cmp_func 函式的 IA32 機械碼前半段是處理 C-style stack,實做部份則是以下兩行組合語言程式碼:
 804838e:       8b 00                   mov    (%eax),%eax
 8048390:       2b 02                   sub    (%edx),%eax
於是我們取上述的機械碼當作 shellcode,改寫之前的範例程式:(qsort-shellcode.c)
#include <stdlib.h>
#include <stdio.h>
 
int array[10] = { 5, 9, 2, 8, 1, 4, 7, 10, 3, 6 };

int main() {                                                                                        
        int i;
        char *shellcode = "\x8b\x00\x2b\x02\xc3";
        qsort(array, 10, sizeof(array[0]), shellcode);
        for (i = 0; i < 10; i++) {
                printf("-> %d\n", array[i]);
        }
        return 0;
}
注意,shellcode 的實做需要補上 ret,否則 qsort 就玩不下去了。
由 jserv 發表於 May 7, 2007 08:18 PM
迴響

很有趣.
但要注意 EAX, EDX 沒正確初始化的情形.

Jye Lu 發表於 May 8, 2007 09:40 AM

it doesn't work on my machine

IMO, it should include all the codes, "\x55...\xc3", with your codes, i got
segment fault, i wonder maybe because of
different compilers?

Joshua 發表於 May 14, 2007 11:34 PM

To Joshua,

I have tested with gcc-4.1 and gcc-3.4 under Ubuntu Linux/IA32. The proper way to use the shellcode is handling stack frame in the correct approach instead of the reduced method I took in the above.

So, it is really interesting that we could write such less portable C-code with customized qsort callback function if we think of being requested.

jserv 發表於 May 15, 2007 12:40 AM

: D

Joshua 發表於 May 17, 2007 02:32 AM

FIXED.

char *shellcode = ""YXZ\x83\xec\f\213\0+\x2\303";
qsort(array, 10, sizeof(array[0]), shellcode);

jserv 發表於 June 23, 2008 12:43 AM
發表迴響









記住我的資訊?