PDA

View Full Version : Reversing GCC



Best Programmer
پنج شنبه 21 دی 1385, 12:30 عصر
در این مقاله کوچیک سعی می کنم دوتا مقایسه بین linux kernel system calls و ‍C library داشته باشم و کمی وارد reverse کردن بشم.

کد Asm (در این کد از کتابخانه C استفاده شده)


section .data
output:
.asciz “This is a test\n”
.section .text
.globl _start
_start:
movl $10, %ecx
loop1:
pushl %ecx
pushl $output
call printf
addl $4, %esp
pushl $5
call sleep
addl $4, %esp
popl %ecx
loop loop1
pushl $0
call exit

و اینجا هم کد asm با استفاده از System call های کرنل لینوکس.(البته با کمی تغییرات روی Freebsd هم جواب میده):


.section .data
timespec:
.int 5, 0
output:
.ascii “This is a test\n”
output_end:
.equ len, output_end – output
.section .bss
.lcomm rem, 8
.section .text
.globl _start
_start:
nop
movl $10, %ecx
loop1:
pushl %ecx
movl $4, %eax
movl $1, %ebx
movl $output, %ecx
movl $len, %edx
int $0x80
movl $162, %eax
movl $timespec, %ebx
movl $rem, %ecx
int $0x80
popl %ecx
loop loop1
movl $1, %eax
movl $0, %ebx
int $0x80

در اینجا ابزاری را استفاده می کنم به اسم strace


% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
89.67 0.001146 115 10 write
2.82 0.000036 2 20 rt_sigprocmask
1.64 0.000021 2 10 rt_sigaction
1.56 0.000020 3 6 old_mmap
1.02 0.000013 4 3 1 open
0.86 0.000011 1 10 nanosleep
0.63 0.000008 4 2 2 access
0.47 0.000006 2 3 fstat64
0.39 0.000005 5 1 munmap
0.31 0.000004 2 2 close
0.23 0.000003 3 1 read
0.23 0.000003 3 1 uname
0.16 0.000002 2 1 brk
------- ---------- ----------- --------- --------- ----------------
100.00 0.001278 70 3 total

این نتایج برگشتی از کد اسمبلی که در آن از کتابخانه C استفاده شده.
و حالا نوبت به system calls می رسه :



% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
90.71 0.000781 78 10 write
9.29 0.000080 8 10 nanosleep
------- ---------- ----------- --------- --------- ----------------
100.00 0.000861 20 0 total


خوب با یه مقایسه ساده بین این اعداد و .... می توان گفت که کدام سریع تر اجرا می شوند. اینجا بحث سر سرعت اجرا نیست. فقط چندتا نتیجه که میتوان گرفت را بیان میکنم :
• در برنامه هاتون بیشتر سعی کنید از systemcall ها به صورت مستقیم استفاده کنید.
• systemcall ها اندازه برنامه شما را کوچیک می کنند چون نیازی به library خارجی ندارند.
• کد شما مستقل از هر گونه کد خارجی میشود.
و در اینجا برای دوستان جبهه دوم :
• کد های فراوان و کتابخانه قوی برای C وجود دارد که کار شما را بسیار آسان می کنند.
• کتابخانه C قابلیت انتقال و اجرا شدن بر روی دیگر Platform ها دارند (مانند *BSD)
• جون کتابخانه C می تواند بین چندین برنامه و تابع به اشتراک گذاشته شود حافظه کمی را نیاز دارد.

((امیدوارم هر دوطرف راضی شده باشند و به بیان نظر های شخصی غیرمطالعه کرده خود ارجاع نکنند .))

در اینجا نیز کمی Reversing :
حتما در مورد Inline Assembly شنیده اید . بد نیست به مقایسه کد نوشته شده C که در آن از inline assembly استفاده شده است با کد disassemble شده همان نگاهی بیاندازیم.


#include <stdio.h>
int a = 10;
int b = 20;
int result;
int main()
{
asm ( "pusha\n\t"
"movl a, "%eax\n\t
"movl b, "%ebx\n\t
"imull %ebx, "%eax\n\t
"movl "%eax, result\n\t
"popa");
printf(“the answer is %d\n”, result);
return 0;
}


همان طور که مشاهده می کنید کد بسیار ساده ای است. در ذیل هم کد disasemble شده همان.


.file “test.c”
.globl a
.data
.align 4
.type a, @object
.size a, 4
a:
.long 10
.globl b
.align 4
.type b, @object
.size b, 4
b:
.long 20
.section .rodata
.LC0:
.string “The result is %d\n”
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
#APP
pusha
movl a, %eax
movl b, %ebx
imull %ebx, %eax
movl %eax, result
popa
#NO_APP
movl result, %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
movl $0, %eax
leave
ret
.size main, .-main
.comm result,4,4
.section .note.GNU-stack,””,@progbits
.ident “GCC: (GNU) 3.3.2 (Debian)”

□ در پایان هم ذکر این موضوع که این کد ها بر اساس AT&T هستند برای دوستانی که تا حال Intel بودند لازم است.
■ در اینجا ابتدا source و بعد distination قرار می گیرد.
■ ابعاد register ها بسیار مهم هستند. (movl )