1. Trang chủ
  2. » Công Nghệ Thông Tin

Cracker Handbook 1.0 part 217 pdf

6 150 1
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 6
Dung lượng 175,54 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Assembly code to C Bây giờ giả sử rằng tôi và các bạn có một đoạn code ASM, và chúng ta có thể đọc hiểu được nó để biết được chương trình đang làm gì.Tuy nhiên, vì hầu hết các câu lệnh

Trang 1

Nhưng nhiệm vụ tiếp theo và rất quan trọng của chúng ta là làm cách nào để biểu đạt đoạn code dưới dạng ASM đó thành đoạn code dưới dạng cú pháp của một ngôn ngữ bậc cao (ví dụ như C)

IV Assembly code to C

Bây giờ giả sử rằng tôi và các bạn có một đoạn code ASM, và chúng ta có thể đọc hiểu được nó để biết được chương trình đang làm gì.Tuy nhiên, vì hầu hết các câu lệnh ASM chỉ thực hiện một nhiệm vụ thông thường, do đó rất khó cho chúng ta biết được tổng quát nhiệm vụ của chương trình đang thực hiện cái gì Hãy xem một đoạn mã ASM dưới đây :

.004122F0: 55 push ebp

.004122F1: 8BEC mov ebp,esp

.004122F3: 83EC48 sub esp,048 ;"H"

.004122F6: 53 push ebx

.004122F7: 56 push esi

.004122F8: 57 push edi

.004122F9: C745F800000000 mov

d,[ebp][-08],000000000 ;"

.00412300: EB09 jmps .00041230B - (1)

.00412302: 8B45F8 mov eax,[ebp][-08]

.00412305: 83C001 add eax,001 ;""

.00412308: 8945F8 mov [ebp][-08],eax

.0041230B: 8B4508 mov eax,[ebp][08]

.0041230E: 50 push eax

.0041230F: FF1584A34300 call lstrlenA ;KERNEL32.dll .00412315: 3945F8 cmp [ebp][-08],eax

.00412318: 7D2E jge .000412348 - (2)

.0041231A: 8B4508 mov eax,[ebp][08]

.0041231D: 0345F8 add eax,[ebp][-08]

.00412320: 8A08 mov cl,[eax]

.00412322: 884DFF mov [ebp][-01],cl

.00412325: 0FB645FF movzx eax,b,[ebp][-01]

.00412329: 83F861 cmp eax,061 ;"a"

.0041232C: 7C18 jl 000412346 - (1)

.0041232E: 0FB645FF movzx eax,b,[ebp][-01]

.00412332: 83F87A cmp eax,07A ;"z"

.00412335: 7F0F jg 000412346 - (2)

Trang 2

.00412337: 0FB645FF movzx eax,b,[ebp][-01]

.0041233B: 83E820 sub eax,020 ;" "

.0041233E: 8B4D08 mov ecx,[ebp][08]

.00412341: 034DF8 add ecx,[ebp][-08]

.00412344: 8801 mov [ecx],al

.00412346: EBBA jmps .000412302 - (3)

.00412348: 5F pop edi

.00412349: 5E pop esi

.0041234A: 5B pop ebx

.0041234B: 8BE5 mov esp,ebp

.0041234D: 5D pop ebp

.0041234E: C3 retn

Bạn thấy đấy, trên đây là một đoạn mã ASM sử dụng rất nhiều các câu lệnh đơn giản kết hợp với nhau và cuối cùng là để thực hiện một nhiệm vụ nào đó mà chính chúng ta cần phải tìm hiểu Chúng ta sẽ bắt đầu làm việc từ câu lệnh đầu tiên và cứ như thế cho đến hết, cố gắng để có một cái nhìn tổng quan nhất về những gì sẽ xảy

ra bằng việc sử dụng một “Pseudo-C” notation (kí pháp Giả ngôn ngữ C), và cuối

cùng là để chuyển nó về chính xác ở C code

Okie có vẻ vẫn hơi mơ hồ, tôi sẽ cùng các bạn giải quyết Đầu tiên chúng ta sẽ bắt đầu với những dòng lệnh sau :

.004122F0: 55 push ebp .004122F1: 8BEC mov ebp,esp .004122F3: 83EC48 sub esp,048 ;"H"

.004122F6: 53 push ebx .004122F7: 56 push esi .004122F8: 57 push edi

Hai dòng lệnh đầu tiên còn được biết đến với một cái tên là “stack frame”.Về bản chất đây là một ‘local’ stack bên trong của hàm, nơi mà chúng ta tưởng tượng như

là một căn phòng đặc biệt dùng để chứa các biến cục bộ (local variables) Việc tạo

ra căn phòng này có thể được thực hiện rất dễ dàng bằng cách đơn giản là giảm con trỏ stack đi một số bit nào đó, cụ thể là bao nhiêu bytes cần thiết cho việc lưu trữ các biến cục bộ

Một trong những lợi thế chính của Stack frame chính là ở thanh ghi EBP, nó có thể

được sử dụng như là một con trỏ cố định tới các biến tham chiếu (reference

Trang 3

varibales) (Nằm ở trên thanh ghi EBP là các tham số, ở dưới nó thì là các biến cục

bộ) (Đọc thêm các bài viết của anh Be)

Chú ý rằng các con trỏ Stack như (ESP và EBP) cần phải được phục hồi lại trước

rời khỏi một hàm nào đó, để tránh cho việc lỗi Stack corruption

.004122F0: 55 push ebp .004122F1: 8BEC mov ebp,esp .004122F3: 83EC48 sub esp,048 ;"H"

Trên đây là quá trình tạo Stack Frame và căn phòng được với không gian là 48 bytes dành cho việc lưu trữ các biến cục bộ

Windows yêu cầu rằng một vài thanh ghi khác ngoài ESP và EBP cũng cần được bảo vệ trong suốt quá trình của một Callback function, đó là những thanh ghi EBX, ESI và EDI Chúng được lưu trữ một cách an toàn trên Stack, và sẵn sàng để khôi

phục lại đúng vị trí trước khi rời khỏi hàm.Điều này cho phép sự tự do khi sử dụng những thanh ghi này bên trong một hàm

Đã có quá trình lưu giữ thanh ghi thì cũng phải có quá trình phục hồi chúng, điều này được thực hiện nhờ vào các câu lệnh rất đơn giản Và nhìn vào đó ta biết ngay

nó làm gì :

.00412348: 5F pop edi .00412349: 5E pop esi .0041234A: 5B pop ebx .0041234B: 8BE5 mov esp,ebp .0041234D: 5D pop ebp

.0041234E: C3 retn

Đầu tiên 3 thanh ghi được khôi phục từ stack của chúng ta Sau đó Stack được phục hồi lại trạng thái của nó sau khi hàm đã được gọi và khi gặp câu lệnh Return Chú ý rằng chúng ta không thể khôi phục Stack trước khi khôi phục 3 thanh ghi được, bởi vì các thanh ghi của chúng đã được lưu trên Stack.Chuyển tất cả đoạn code trên sang C là rất dễ dàng Bây giờ chúng ta biết rằng đây có thể là một hàm, bởi vì dựa vào Stack Frame cũng như việc lưu trữ và phục hồi các thanh ghi,

v v :

void SomeFunction() {

Trang 4

//…code…

}

Bây giờ tôi giả sử rằng đây là một void function, bởi vì không hề có bất kì một sự

thay đổi nào trong thanh ghi EAX trước khi Return Điều đó không có nghĩa là EAX đã không bị thay đổi Nhưng cho đến bây giờ, chúng ta sẽ giả sử giá trị trong thanh ghi EAX bị lờ đi

Tiếp theo chúng ta sẽ tiếp tục với thân của hàm này :

.004122F9: C745F800000000 mov

d,[ebp][-08],000000000 ;"

.00412300: EB09 jmps .00041230B - (1)

.00412302: 8B45F8 mov eax,[ebp][-08]

.00412305: 83C001 add eax,001 ;""

.00412308: 8945F8 mov [ebp][-08],eax

.0041230B: 8B4508 mov eax,[ebp][08]

.0041230E: 50 push eax

.0041230F: FF1584A34300 call lstrlenA ;KERNEL32.dll .00412315: 3945F8 cmp [ebp][-08],eax

.00412318: 7D2E jge .000412348 - (2)

Chúng ta hãy để ý tới giá trị được tham chiếu đến :

d,[ebp][-08] == dword ptr[ebp-08] (in another notation)

Như tôi đã nói, bời vì nó nằm dưới thanh ghi EBP của chúng ta (thanh ghi EBP

đang được lưu trên Stack), vì vậy hàm đang lưu trữ một biến cục bộ ở đó Chúng ta biết được rằng nó có kích thước là DWORD và nó có thể là một giá trị có dấu

(signed value), bởi nó được đem đi so sánh với kết quả của hàm lstrlenA, mà kết

quả của hàm này là một signed int) Trên nền tảng win32, thì giá trị signed dword

trong C là (signed) int Chúng ta hãy đổi tên của nó thành int_locall để cho việc

đọc hiểu trở nên dễ dàng hơn :

.004122F9: mov int_local1, 000000000 .00412300: jmps .00041230B - (1) .00412302: mov eax, int_local1

.00412305: add eax,001 .00412308: mov int_local1, eax .0041230B: mov eax,[ebp][08]

Trang 5

.0041230E: push eax .0041230F: call lstrlenA ;KERNEL32.dll .00412315: cmp int_local1,eax

.00412318: jge .000412348 - (2)

Okie đã thấy sáng sủa hơn một chút, tuy nhiên các bạn hãy cẩn thận ở đây, đừng

nhầm lần giữa [ebp][08] với [ebp][-08] Mặc dù là nhìn thoáng qua ta cũng thấy

nó giống nhau đấy chứ, tuy nhiên đây lại là những địa chỉ hoàn toàn khác nhau

Biến tại địa chỉ [ebp][08] thì luôn luôn là một tham số đầu tiên được truyền vào

hàm của chúng ta Chính vì lí do đó chúng ta sẽ đổi tên của giá trị này thành

dw_param1 Khà khà sau một hồi phân tích chúng ta đã xác định được biến cục

bộ, và làm sáng tỏ được một số vấn đề , bây giờ chúng ta sẽ thử chuyển nó sang một đoạn mã giả C :

int_local1 = 0;

goto label_41230B;

eax = int_local1;

eax = eax + 1;

int_local1 = eax;

label_41230B:

eax = dw_param1;

eax = lstrlenA(eax); //lstrlenA returns its result in eax if( int_local1 >= eax)

goto label_412348;

Vậy là phần nào chúng ta đã có một cái nhìn dễ dàng hơn với đoạn code trên, tuy nhiên đây mới chỉ là điểm khởi đầu.Việc tiếp theo chúng ta phải dùng tư duy của mình để tối ưu hóa lại đoạn code này, hãy nhìn lại 3 dòng sau :

eax = int_local1;

eax = eax + 1;

int_local1 = eax;

Chúng ta sẽ thấy rằng đoạn code trên là hơi thừa nó có thể được đơn giản hóa lại như sau :

int_local1++;

Trang 6

Điểm khác biệt duy nhất giữa hai cách thể hiện này là thanh ghi EAX không xuất

hiện trong cách biểu diễn thứ hai Chúng ta cần phải cẩn thận quan sát, vì rất có thể

giá trị của thanh ghi EAX sẽ lại được sử dụng ở phía bên dưới thì sao 

Tiếp theo ta đến dòng kế tiếp :

Ngày đăng: 03/07/2014, 17:21

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN