banner

[Rule] Rules  [Home] Main Forum  [Portal] Portal  
[Members] Member Listing  [Statistics] Statistics  [Search] Search  [Reading Room] Reading Room 
[Register] Register  
[Login] Loginhttp  | https  ]
 
Forum Index Thảo luận hệ điều hành Windows .:Hack Windows:.  XML
  [Question]   CISC 22/01/2008 22:45:39 (+0700) | #31 | 111550
Reversing...
Member

[Minus]    0    [Plus]
Joined: 31/12/2007 06:28:04
Messages: 117
Location: -1.-1.-1.-1
Offline
[Profile] [PM] [Yahoo!]
Dưới đây tớ xin vắn tắt một vài cấu trúc lệnh ngôn ngữ máy. Để thực thi có thể dùng trình Debug trong win.
Thực chất khoảng cách giữa Assembler và Ngôn ngữ máy là khá xa. Với một cấu trúc lệnh, trong Asm bạn có thể dễ dàng chỉ ra được, còn với ngôn ngữ máy thì bạn phải đứng trước hàng trăm lựa chọn. Nói thế thôi, đọc xong vài dòng dưới đây, chắc các bạn cũng có thể tự mình code bằng computer language được rồi.
Format:
opcode - - operand 
( hay Toán tử - Toán hạng )
1. Bit - Byte - Word - DWord
2. Bit là gì? Đó là lượng thông tin chứa trong một vật. Làm sao để biết? - Chẳng hạn một mảng các số từ 1 đến 8 sẽ mang một lượng thông tin là 3 bit. Tức là có thể thay thế 1 bởi 000, 2 bởi 001,... 8 bởi 111.
Dòng CPU 32bit dùng 8 thanh ghi mở rộng sau: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP. Như thế, ta có thể xem các thanh ghi này nằm trong khoảng 000 đến 111 ( 3 bit ).
3. Thử xem 2 câu lệnh assembler sau có gì khác nhau?

mov byte ptr [esi], 0
mov dword ptr [eax], 1
 

Cũng là 0, cũng là 1, nhưng 0 ở trên là 00000000 ( 1 byte ), còn 1 ở dưới là 00...001 ( 31 con số 0 ), tức 1 ở đây được biểu diễn ở dạng 4 bytes. Chính đây cũng là số byte chứa trong EAX , EBX và các thanh ghi mở rộng khác.
4. Để "quậy", có lẽ ta chỉ cần xem xét lệnh MOV là đủ. Hãy xem có những trường hợp nào được xét đến:

a---- Chuyển dữ liệu trực tiếp ( tức một hằng số ) vào thanh ghi.
b----Chuyển dữ liệu từ thanh ghi vào bộ nhớ
c---- Chuyển dữ liệu từ bộ nhớ vào thanh ghi
 

Xét a-
Cấu trúc câu lệnh là:
1011 w reg <các byte dữ liệu> 

w là một bit. w = 0 nếu MOV chuyển 1 byte dữ liệu vào register, và w = 1 nếu chuyển 4 bytes vào register.
Ví dụ :
10111000 00000001 00000000 00000000 00000000  

sẽ chuyển 1( 32 bit ) vào EAX. Ở đây, 32 bit của 1 được viết theo kiểu ngươc lại. Chẳng hạn 12345678h -sẽ được viết là 78h 56h 34h 12h. ( h đây là HEX = 4 bit ). EAX = 000. Bit w = 1 ( mov 32 bit ).

Xét b- và c-
Cấu trúc câu lệnh là:
101000 d w <các byte địa chỉ

Chú ý lúc này ta chuyển dữ liệu nhờ vào địa chỉ của vùng nhớ. Và 1 địa chỉ chứa 4 bytes.
Trong câu lệnh không có thanh ghi bởi ta xem lúc này CPU đang làm việc với EAX hoặc các phần của nó ( AX, AH , AL)
bít d ở đây có nghĩa là direction, d = 0 nếu chuyển từ bộ nhớ vào thanh ghi và d = 1 nếu từ thanh ghi vào bộ nhớ.
w = 0 hay 1 nếu ta xét EAX hay AL.
Ví dụ:
10100001 00000001 00000000 00000000 00000000 
copy giá trị chứa tại địa chỉ 1 vào thanh ghi EAX. ( Tại sao? )
còn
10100000 00000001 00000000 00000000 00000000 
copy giá trị chứa tại địa chỉ 1 vào AL ( d = w = 0 ).
Và các bạn thử để ý: Ta chỉ thay đổi 1 bit để làm một công việc không đơn giản.

5. Bây giờ là phần lý thú nhất. Giả sử ta muốn chuyển dữ liệu giữa 2 thanh ghi thì làm thế nào?
Trong cấu trúc lệnh của CPU 32bit có hỗ trợ một byte phương pháp địa chỉ (ModR/M). Cấu trúc byte này như sau:
2 bit MOD - 3 bit REG - 3 bit R/M 


Byte này có nghĩa là trong câu lệnh phải có 2 toán hạng, và một trong 2 phải là thanh ghi ( code nằm trong 3 bit REG ), toán hạng còn lại có thể nằm trong thanh ghi (khi MOD = 11; lúc này R/M chứa code của register.), hoặc nằm trong bộ nhớ. (R/M="register or memory"smilie.
Ở trường hợp thứ hai, ta dùng bảng sau để tham chiếu địa chỉ cho bộ nhớ:

R/M | MOD=00 | MOD=01 | MOD=10 |
000 | [EAX] | [EAX] + 1 | [EAX] + 4 |
001 | [ECX] | [ECX] + 1 | [ECX] + 4 |
010 | [EDX] | [EDX] + 1 | [EDX] + 4 |
011 | [EBX] | [EBX] + 1 | [EBX] + 4 |
100 | SIB | SIB + 1 | SIB + 4 |
101 | 4 | [EBP] + 1 | [EBP] + 4 |
110 | [ESI] | [ESI] + 1 | [ESI] + 4 |
111 | [EDI] | [EDI] + 1 | [EDI] + 4 |
 

Giả sử ta muốn copy từ EAX vào EBX. Cả hai toán hạng đều nằm trong registers nên MOD=11; Toán hạng thứ nhất năm trong EAX --> REG=000; cái thứ hai nằm trong EBX --> R/M=011; Tổng cộng ta thu được byte ModeR/M là 11000011 (C3). Opcode: toàn bộ 32 bit nên w=1; hướng từ register vào r/m nên d=0. Cấu trúc lệnh thu được sẽ là:
10001001 11000011 (89 C3). 

[ Một bài tập nhỏ: Hãy thử thiết lập câu lệnh copy từ EBX vào EAX ]
Thật sự ta sẽ thu được một câu lệnh khác với cấu trúc ở trên. Nhưng chúng không có gì khác nhau. Trong Assembler, 2 cấu trúc này được viết là :
MOV EAX, EBX  
.

Hy vọng các bạn sẽ không còn bỡ ngỡ khi phải debug một chương trình nào đó.
Chúc vui!
Rev.
-------------------------------------------------------------------------------------------------------------
[Up] [Print Copy]
  [Question]   Re: .:Hack Windows:. 23/01/2008 00:09:29 (+0700) | #32 | 111571
[Avatar]
Angelvn
Member

[Minus]    0    [Plus]
Joined: 13/05/2007 21:39:58
Messages: 27
Location: Viet Nam
Offline
[Profile] [PM]
Bài trên đọc thấy quen quen...

@Reversing...: bồ tự viết bài này à?
Shut up and Get down.
[Up] [Print Copy]
  [Question]   Window khởi động như thế nào? 23/01/2008 17:07:15 (+0700) | #33 | 111701
Reversing...
Member

[Minus]    0    [Plus]
Joined: 31/12/2007 06:28:04
Messages: 117
Location: -1.-1.-1.-1
Offline
[Profile] [PM] [Yahoo!]
@Anglevn: bài viết trên thực chất chỉ là một phần rất nhỏ trong môn cấu trúc máy tính ( có lẽ bạn chưa được học đến ?). Nó nằm ở phần CPU và bộ lệnh của CPU. Mình đã viết đơn giản đến mức có thể , còn cái lý thuyết của nó thì cồng kềnh hơn nhiều smilie.
Hôm nay lang thang ở web của Microsoft tậu được cái này, đưa lên mọi người tham khảo. Chắc chắn sẽ có nhiều điều khó hiểu. Bên trong máy tính của ta đã xảy ra những gì khi ta bật nguồn ?

1)Đầu tiên là bộ phận nguồn.
Khi bật máy lên, bộ này gởi tín hiệu Power Good đến CPU

2)Đồng hồ trong CPU nhận được tín hiệu Power Good.
Nó sẽ thôi gởi các tín hiệu Reset đến CPU.

3)CPU thực hiện code ROM BIOS.
Bắt đầu từ địa chỉ FFFF:0000.Đây thực chất chỉ là địa chỉ trỏ đến địa chỉ thực sự của ROM BIOS .

4)Kiểm tra phần cứng.
Hệ thống màn hình vẫn chưa được khởi tạo nên lúc này mọi lỗi xảy ra sẽ được phát qua âm thanh.

5)Card màn hình:
Các thủ tục khởi động tiến hành quét bộ nhớ từ địa chỉ C000:0000 đến C780:0000 để tìm video ROM.

6)ROM BIOS kiểm tra xem đây là tắt máy hay restart:
Thông qua 2 byte chứa trong địa chỉ 0000:0472. Mọi giá trị khác với 1234h đều cho biết đây là khởi động nguội.

7)Nếu là khởi động ROM BIOS cho chạy toàn bộ POST (Power On Self Test). Nếu là khởi động lại thì POST chỉ kiểm tra bộ nhớ.

8)BIOS đọc các thông tin cấu hình từ CMOS:
Một phần bộ nhớ (64 байт) được cung cấp điện trên bo mạch chủ. Nhiệm vụ lúc này là xác định xem cái gì được nạp trước: CD-ROM, CD hay đĩa cứng.

9)Nếu là đĩa cứng, BIOS kiểm tra sector đầu tiên trên đĩa về Master Boot Record (MBR). Nếu là ổ CD thì kiểm tra Boot Record ở sector đầu tiên.
Master Boot Record - 512 byte được load vào bộ nhớ tại địa chỉ 0000:7C00, sau đó kiểm tra 2 byte signature - phải là 55AAh.
10)Việc thiếu MBR hay 2 byte này buộc quá trình boot dừng lại. MBR bao gồm 2 phần : partition loader hay Boot loader, chương trình nhận được điều khiển khi khởi động đĩa cứng, thứ hai là bảng phân vùng chứa thông tin về các đĩa logic nằm trên đĩa vật lý

11)Code MBR được thực hiện:
Chọn ổ đĩa chứa hệ điều hành.
Boot Loader kiểm tra bảng phân vùng . và tìm kiếm Boot Record tại sector đầu tiên trên đĩa.
Boot Record - 512 byte là bảng chứa miêu tả của phân vùng (số byte trong 1 sector, số sector trong một cluster ... và chuyển đến file đầu tiên của hệ điều hành (IO.SYS trong DOS).

12)Lúc này điều khiển hệ thống đưa cho Hệ điều hành.
Việc khởi động của Windows XP được kiểm tra bởi file NTLDR, nằm trong thư mục gốc của phân vùng hệ thống. NTLDR làm việc 4 bước:
Xác định phần cứng
Lựa chọn cấu hình.
Đầu tiên NTLDR chuyển processor vào chế độ bảo vệ. Sau đó khởi động driver hệ thống file giúp hdh làm việc với hệ thống file trên đĩa, FAT-16, FAT-32 hay NTFS.

13)Nếu trong thư mục gốc có file BOOT.INI, thì nội dung của nó được đưa vào bộ nhớ . Nếu trong đó có ghi hơn một hệ điều hành, NTLDR dừng công việc của mình và đưa ra menu chọn lựa hệ điều hành trong một khoảng thời gian nhất định.
Nếu file này không có, NTLDR tiếp tục từ bảng phân vùng nằm trên đĩa, lúc này nó làm việc với ổ C:/

14)Nếu người dùng chọn Windows NT, 2000 hay XP, NTLDR kiểm tra việc có nhấn F8 hay không để kiểm tra setup lúc khởi động.
Sau mỗi lần khởi động thành công, hệ điều hành lưu lại danh sách các driver và cấu hình , có tên gọi Last Known Good Configuration.

15)Nếu người dùng chọn Window XP, NTLDR tìm và chạy chương trình DOS là NTDETECT.COM để xác định phần cứng của máy tính.
NTDETECT.COM xây dựng các thành phần, các thành phần này sau đó được đưa vào registry tại nhánh HARDWARE tại HKEY_LOCAL_MACHINE.

16)Sau phần lựa chọn cấu hình NTLDR bắt đầu cho chạy nhân XP(kernel) (NTOSKRNK.EXE).
Trước khi nhân được khởi động thì NTLDR chính là "đạo diễn" trong quá trình khởi động của máy tính. Ngoài nhân ra, còn có Hardware Abstraction Layer (HAL.DLL) nằm trong thư mục System32 được khởi động.

17)NTLDR khởi động driver các thiết bị
Mỗi driver có khóa riêng tại nhánh HKEY_LOCAL_MACHINE\SYSTEM\Services. Nếu giá trị Start là SERVICE_BOOT_START, thì thiết bị sẽ được chạy lúc khởi động.

18)NTOSKRNL trải qua 2 pha. Pha đầu tiên khởi tạo một phần của nhân và các hệ thống con cần thiết cho các service .Tại pha thứ hai cho dấu hiêu ra màn hình.
XP kiểm tra các ngắt tại pha đầu tiên và khởi tạo các service: Memory Manager, Object Manager, Security Reference Monitor và Process Manager.Pha thứ hai bắt đầu khi HAL chuẩn bị cho hệ điều hành xử lý các ngắt . Tất cả hệ thống con được khởi tạo theo trình tự sau:
Object Manager
Executive
Microkernel
Security Reference Monitor
Memory Manager
Cache Manager
LPCS
I/O Manager
Process Manager


19)
Việc khởi tạo I/O Manager bắt đầu tiến trình khởi động các driver hệ thống . Từ lúc này NTLDR dừng công việc.
Sai sót trong việc khởi động driver có thể bắt máy tính khởi động lại và bắt đầu lại Last Known Good Configuration.

20)Nhiệm vụ sau cùng của pha thứ hai là khởi động Session Manager Subsystem (SMSS). Hệ thống này đảm bảo các profile cho người sử dụng. Nó đưa ra màn hình login lúc đăng nhập.
SMSS lại khởi động win32k.sys - hệ thống đồ họa.
Driver chuyển máy tính vào chế độ đồ họa , SMSS cho bắt đầu tất cả các service được cho chạy lúc khởi động. Tiếp tục là quá trình tạo Last Known Good Configuration.
Quá trình khởi động được xem là không thành công nếu ngừoi dùng vẫn chưa đăng nhập vào hệ thống. Quá trình này được khởi tạo bởi file WINLOGON.EXE, được xem là service và chịu sự quản lý của Local Security Authority (LSASS.EXE).
Cuối cùng là các net service.

[Up] [Print Copy]
  [Question]   Re: .:Hack Windows:. 23/01/2008 23:14:46 (+0700) | #34 | 111723
[Avatar]
Look2Me
Member

[Minus]    0    [Plus]
Joined: 26/07/2006 23:30:57
Messages: 235
Location: Tủ quần nào
Offline
[Profile] [PM]
Bực mình quá! Xin lỗi mấy bồ chứ, các bồ ở trình độ nào mà đọc bài trên bảo là leech bài với chẳng quen quen. Nên tôn trọng người khác một tý. Nếu bạn thấy nghi ngờ là copy left thì làm ơn tìm rõ chứng cứ, tìm được bằng chứng cụ thể thì hãy nói. Còn không đề nghị ngồi yên mà nghe. Cho dù đó là bài leech đi chăng nữa, mong bạn reversing cứ post lên vì đơn giản là tôi đang muốn theo dõi.
Ghét cái bọn phá bĩnh diễn đàn.
Bức xúc.
[Up] [Print Copy]
  [Question]   Debug or Crack? 24/01/2008 22:11:59 (+0700) | #35 | 111918
Reversing...
Member

[Minus]    0    [Plus]
Joined: 31/12/2007 06:28:04
Messages: 117
Location: -1.-1.-1.-1
Offline
[Profile] [PM] [Yahoo!]
Trong các bạn ở đây, có lẽ có nhiều người chưa từng crack lần nào, và thậm chí chưa biết crack là gì. Trong 3 bài viết dưới đây, tớ sẽ hướng dẫn từng bước để các bạn có thể tự mình crack một chương trình. Sơ đồ như sau:

1) Căn bản về x86 Assembly Language và ngôn ngữ C.
2) Debug & Dissasembler
3) Patch
 

Các bạn chỉ cần Visual Studio 2005 và Far v1.7 .
-----------------------------------------------------------------------------------------------------------------------------------
$1. Assembly
Xin xem thêm chi tiết tại đây

1.Kiểu dữ liệu và biến:
+Khai báo biến:

Dữ liệu có thể chứa ở các thanh ghi ( registers ) hoặc bộ nhớ (memory). Tốc độ truy cập tại registers nhanh hơn so với memory. Ở phần cấu trúc ngôn ngữ máy, ta đã nói về các thanh ghi. Cần nhớ là 1 Byte = 8 bit, 1 Word = 2 Byte (16 Bit), 1 DWORD = 32 bit ( 4 bytes )
Cấu trúc hợp ngữ khai báo biến như sau:

done db 0 ; 1 byte (8 bits),khởi tạo bằng 0
length dw ? ; 1 word (16 bits), không được khởi tạo giá trị
count dd 0 ; 1 dword (32 bits), khởi tạo bằng 0
name db 40 dup(?) ; 40 bytes, không được khởi tạo
 


Cấu trúc câu lệnh trong Assembly như sau:

opcode register
opcode register, memory
opcode memory, register
opcode register, register
opcode register, immediate
 

Điều lưu ý ở đây là 2 cấu trúc vàng ở trên. Như đã nói, trong lệnh MOV, ta cần chỉ rõ là MOV bao nhiêu byte từ memory ( hay immediate ) vào register. Thường số byte được mov phụ thuộc vào hạng tử đứng trước, chẳng hạn trong câu lệnh: mov eax, [esp], 32 byte ở vùng nhớ có địa chỉ nằm trong esp sẽ được đưa vào eax. Nhưng nếu hạng tử đứng trước có số bit xác định thì sao? Lúc này có thể dùng các cấu trúc sau:

mov byte ptr [esi], 0 ; move 1 byte
mov dword ptr [eax], 1 ; move 1 dword
inc word ptr [ebx] ; increment 1 word tại [ebx]
 

Giả sử, ta có câu lệnh như sau: mov dword ptr [eax], 0x12345678. Bây giờ theo các bạn bxcl sẽ chứa giá trị bao nhiêu?

mov bx, word ptr [eax] ;
mov cl, byte ptr [eax] ;
 

Lúc này:
bx = 0x5678
cl = 0x78

Đây chính là điểm cần lưu ý khi ta muốn copy dữ liệu là một số hex vào register.

+ Làm việc với Stack:

Stack là một vùng nhớ được hệ điều hành cấp phát cho chương trình để lưu các giá trị tạm thời, các giá trị đó có thể là các biến, một địa chỉ, hay một hằng số. Chẳng hạn khi ta muốn gọi một hàm có chứa tham số, thì ta phải lưu tạm thời các tham số đó vào đâu đó để sử dụng trong hàm. "Đâu đó" ở đây có thể là stack hoặc registers. Nhưng nếu lưu vào register thì ta lại phải lưu tiếp giá trị cũ của các registers vào đâu đó để thay thế bằng các tham số cho hàm. Chính điều này mà trong các bộ dịch ( compiler ), chính các tham số sẽ được đưa vào stack chứ không phải các thanh ghi.
Ta dùng pushpop để làm việc với stack:

push eax ; đưa giá trị của eax vào stack
pop ebx ; lấy giá trị tại đỉnh stack và đưa vào ebx
 

Thực chất của 2 câu lệnh trên như sau:
Địa chỉ vị trí hiện thời tại stack được cất tại một thanh ghi khác, là esp, mà tại đây ta được phép đọc và ghi. Đầu tiên push trừ giá trị của exp để lưu giá trị vào [esp]. Sau đó pop đọc giá trị [esp] và cộng lại giá trị cho esp.
Như thế, ta thấy rằng:

mov eax, [esp] ----------> lúc này esp không được cộng thêm để trở về giá trị ban đầu.
 


pop edx sẽ tương đương với:
mov edx, [esp]
add esp, 4


và push ax sẽ tương đương với:
sub esp, 2
mov [esp], ax

+ Ngoài mov , cấu trúc lea cho phép nhận giá trị offset của thanh ghi khác như sau:
lea esi, [edi+8] tương đương với
mov esi, edi
add esi, 8


2. Các phép tính số học:
Đối với các phép cộng và trừ.

add ebp, eax ; ebp = ebp + eax
add byte ptr [esi], 5 ; [esi] = [esi] + 5
sub cl, ch ; cl = cl – ch
sub mybyte, al ; mybyte = mybyte - al
 

Với phép nhân và chia thì có hơi khác một tí, lúc này nơi chứa giá trị trả về không đơn thuần là một thanh ghi. Ví dụ:

mul al, bl ; ax = al * bl
mul ax, cl ; dx:ax = ax * cl
mul eax, ebx ; edx:eax = eax * ebx
 

dx:ax = ax * al chỉ ra rằng giá trị trả về sẽ là giá trị 32 bit, 16 bit cao được chứa tại dx, 16 bit thấp được chứa tại ax.

Một vài phép tính nữa được liệt kê dưới đây

;Dịch trái, dịch phải một số byte
shl eax, 4 ; eax = eax * 16
shr al, 1 ; al = al/2
; Cộng, trừ và phủ định
inc eax ; eax = eax + 1
dec word ptr [esi] ; [esi] = [esi] - 1
neg ah ; ah = 0 – ah

; Các phép tính logic:

and eax, ebx ; eax = eax & ebx
or al, ah ; al = al | ah
xor edx, dword ptr [edi] ; edx = edx ^ [esi]
not dx ; dx = ~dx
 



3) Các cở

Có một thanh ghi đặc biệt của CPU chứa các cờ. Các cờ chỉ ra dấu hiệu nhận biết. Chẳng hạn nếu bạn thao tác với một biến x sao cho nó bằng 0, thì cờ Zero Flag sẽ được "dựng" lên. Một số loại cờ tương tự như thể có tên gọi là các cờ trạng thái. Có 4 loại cờ chính: Carry, Zero, Sign, và Overflow . Chẳng hạn, Sign Flag sẽ chứa giá trị của bit dấu của kết quả. Nếu kết quả là số âm, SF ( sign flag ) = 1. ( Tại sao? ).
Cách sử dụng như thế nào?
Ví dụ như sau:

sub ecx, 1
jz mylabel ; như thế phép trừ sẽ tác động vào cờ zero flag, nếu ecx = 0 thì chương trình nhảy đến nhãn mylabel( nằm ở một nơi nào đó trong chương trình )
;;;;;;;;;;;
test eax, 0x02 ; lệnh test thực hiện phép logic and. Như thế nếu bit thứ 2 của eax = 0 thì chương trình nhảy đến
jz mylabel ; mylabel.
 


Dưới đây là bảng cho so sánh của các cờ:

equal/unequal:

je/jz equal/zero (ZF = 1)
jne/jnz not equal/not zero (ZF = 0)

So sánh không dấu:

ja/jnbe above/not below or equal (CF = 0 and ZF = 0)
jae/jnb above or equal/not below (CF = 0)
jb/jnae below/not above or equal (CF = 1)
jbe/jna below or equal/not above (CF = 1 or ZF = 1)

So sánh có dấu:

jg/jnle greater/not less or equal (ZF = 0 and SF = OF)
jge/jnl greater or equal/not less (SF = OF)
jl/jnge less/not greater or equal (SF != OF)
jle/jng less or equal/not greater (ZF = 1 or SF != OF)
 


4) Cấu trúc nhảy:
Phần này ta sẽ nói tóm tắt thông qua ví dụ:

mov ecx, 10
topofloop:
; Các phép toán ở đây
sub ecx, 1
jnz topofloop
 

Nếu dùng loop thì sẽ đơn giản hơn ở chỗ là nó sẽ lấy ecx làm biến đếm.Tức sau mỗi lời gọi loop, ecx sẽ tự động trừ đi1

mov ecx, 10
topofloop:
; operations
loop topofloop
 

5) Thủ tục ( hàm ):
Lời gọi thủ tục được thực hiện qua lệnh CALL sẽ gọi điạ chỉ của thủ tục cần gọi ra.
CALL myfunction
Điều duy nhất lệnh CALL làm là đưa giá trị của eip vào stack sau đó nhảy đến hàm. Để thoát khỏi hàm thì dùng lệnh ret

ret
 

ret sẽ lấy giá trị ở đỉnh ( eip ban đầu ) và đưa chương trình nhảy đến giá trị đó ( tức là chương trình được tiếp tục bởi eip chứa địa chỉ của dòng lệnh tiếp sau dòng lệnh CALL myfunction ). Có thể xem ví dụ sau:

push 0
ret ; chương trình nhảy đến nhảy đến địa chỉ 0 !
 

Với hàm có tham số, chẳng hạn, trong ngôn ngữ C, tính chất lời gọi hàm được quy định là stdcall , tức là các tham số được đưa vào stack từ phải qua trái, như ví dụ sau:
my_func (a, b, c);
tương đương trong assembly như sau:

push c
push b
push a
call my_func
 

Còn trong ngôn ngữ Pascal, các tham số lại được đưa từ trái qua phải vào stack

push a
push b
push c
call my_func
 

Điều đó cho thấy, mỗi ngôn ngữ bậc cao quy định một kiểu làm việc riêng lên stack.
Phần cuối cùng là làm việc với các biến địa phương trong hàm.
Ta nhớ lại thanh ghi esp. Chính khi khai báo một biến địa phương , ta sẽ trừ đi giá trị của esp, chẳng hạn:

sub esp, 8
 

sẽ dành ra một vùng nhớ cho 2 dwords, mà ta có thể truy xuất thông qua [esp] hoặc là [esp + 4].
Như thế, ta có thể thấy sự khó khăn khi phải làm bằng tay công việc này, bởi trước khi gọi ret để thoát khỏi hàm, ta phải ý thức được esp phải trỏ tại giá trị eip , tức là phải đưa chương trình chạy đúng quỹ đạo của nó.

Phần 1 đến đây kết thúc. Ở phần sau, ta sẽ nói về ngôn ngữ C và làm thế nào để debug một chương trình.
Chúc vui.
Rev.
[Up] [Print Copy]
  [Question]   Hàm trong C 01/02/2008 19:03:09 (+0700) | #36 | 113247
Reversing...
Member

[Minus]    0    [Plus]
Joined: 31/12/2007 06:28:04
Messages: 117
Location: -1.-1.-1.-1
Offline
[Profile] [PM] [Yahoo!]
Ta thử viết lại đoạn code viết bằng C sau lại trên ngôn ngữ assembly:

Code:
func();
main()
{
       int a;
       func();
       a=0x666;
       func();
}

func()
{
       int a;
       a++;
}

Giả sử địa chỉ bắt đầu đoạn code trên của ta là .text:00401000. Lúc đó, 2 câu lệnh assembly đầu tiên sẽ là:

.text:00401000 push ebp
.text:00401001 mov ebp, esp
 

_ ebp được dùng để lưu lại giá trị ban đầu của esp. Điều này là cần thiết, bởi nếu trong hàm có biến địa phương thì esp sẽ bị trừ lui đi một số byte địa chỉ.
Tiếp tục với chương trình, câu lệnh assembly tiếp theo sẽ là:

.text:00401003 call 401018
 

_ Lúc này 401018 chính là địa chỉ của hàm func() mà ta sẽ nhảy đến.
Tiếp tục,
.text:00401008 mov dword ptr [ebp-4], 666h 
tương đương với a = 0x666

.text:00401009 call 401018
.text:00401014 mov esp, ebp
.text:00401016 pop ebp
.text:00401017 retn
 

_ 3 câu lệnh sau cùng trả lại giá trị ban đầu cho esp để thoát khỏi hàm.
Và cuối cùng là hàm func()

.text:00401018 push ebp
.text:00401019 mov ebp, esp
.text:0040101B push ecx
.text:0040101C mov eax, [ebp-4]
.text:0040101E add eax, 1 ;-----> Thân của hàm tại đây
.text:00401022 mov [ebp-4], eax
.text:00401025 mov esp, ebp
.text:00401027 pop ebp
.text:00401028 retn
 


Như thế ta đã làm rõ được phần nào cơ chế làm việc của hàm thông qua stack như thế nào.

[Up] [Print Copy]
  [Question]   Authentication 02/02/2008 05:24:10 (+0700) | #37 | 113291
Reversing...
Member

[Minus]    0    [Plus]
Joined: 31/12/2007 06:28:04
Messages: 117
Location: -1.-1.-1.-1
Offline
[Profile] [PM] [Yahoo!]
Bây giờ ta viết một chương trình nhỏ kiểm tra password nhập vào, nếu đúng thì chương trình hiển thị dòng chữ Hello, nếu sai thì "Wrong password". Tất cả nằm trong câu lệnh:
if (strcmp (password nhập vào, password đúng)) {/* Wrong password */} else {/* Hello*/}.
 

Có thể dùng Visual Studio 2005 để biên dịch.
Code:
#include <iostream>
#include <string>
using namespace std;
#define PASSWORD_SIZE 100
#define PASSWORD "mypassword\n"
int main()
{
        int count = 0; // kiểm tra số lần thử
        char buffer[PASSWORD_SIZE];    
        for(;;)
        {
                    if(++count > 3) return -1;
                    cout <<"Enter password: ";
                    cin.getline(buffer, PASSWORD_SIZE);
                    if (strcmp(buffer, PASSWORD))
                            cout << "Wrong password\n" ;
                    else
                    {
                            cout <<"Hello\n";
                            break;
                    }
       }
       system("pause");
       return 0;
}


Dịch và tạo một file password.exe. Bây giờ nếu dùng IDAPro thì ta thu được code assembly như sau:
Code:
int __cdecl main(int argc, const char **argv, const char *envp)
.text:00401390 _main           proc near               ; CODE XREF: ___mingw_CRTStartup+E2p
.text:00401390
.text:00401390 var_A8          = dword ptr -0A8h
.text:00401390 var_A4          = dword ptr -0A4h
.text:00401390 var_A0          = dword ptr -0A0h
.text:00401390 var_8C          = dword ptr -8Ch
.text:00401390 var_88          = byte ptr -88h
.text:00401390 var_C           = dword ptr -0Ch
.text:00401390 argc            = dword ptr  8
.text:00401390 argv            = dword ptr  0Ch
.text:00401390 envp            = dword ptr  10h
.text:00401390
.text:00401390                 push    ebp
.text:00401391                 mov     ebp, esp
.text:00401393                 sub     esp, 0A8h
.text:00401399                 and     esp, 0FFFFFFF0h
.text:0040139C                 mov     eax, 0
.text:004013A1                 add     eax, 0Fh
.text:004013A4                 add     eax, 0Fh
.text:004013A7                 shr     eax, 4
.text:004013AA                 shl     eax, 4
.text:004013AD                 mov     [ebp+var_8C], eax
.text:004013B3                 mov     eax, [ebp+var_8C]
.text:004013B9                 call    ___chkstk
.text:004013BE                 call    ___main
.text:004013C3                 mov     [ebp+var_C], 0
.text:004013CA
.text:004013CA loc_4013CA:                           ; CODE XREF: _main+C1j
.text:004013CA                 cmp     [ebp+var_C], 3
.text:004013CE                 jg      loc_401456
.text:004013D4                 mov     [esp+0A8h+var_A4], offset aEnterPassword ; "Enter password: "
.text:004013DC                 mov     [esp+0A8h+var_A8], offset dword_4433C0
.text:004013E3                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
.text:004013E8                 mov     [esp+0A8h+var_A0], 64h
.text:004013F0                 lea     eax, [ebp+var_88]
.text:004013F6                 mov     [esp+0A8h+var_A4], eax
.text:004013FA                 mov     [esp+0A8h+var_A8], offset dword_443460
.text:00401401                 call    __ZNSi7getlineEPci
.text:00401406                 lea     eax, [ebp+var_88]
.text:0040140C                 mov     [esp+0A8h+var_A4], offset aMypassword ; "mypassword"
.text:00401414                 mov     [esp+0A8h+var_A8], eax
.text:00401417                 call    strcmp
.text:0040141C                 test    eax, eax
.text:0040141E                 jz      short loc_401436
.text:00401420                 mov     [esp+0A8h+var_A4], offset aWrongPassword ; "Wrong password\n"[/color]
.text:00401428                 mov     [esp+0A8h+var_A8], offset dword_4433C0
.text:0040142F                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
.text:00401434                 jmp     short loc_40144C
.text:00401436 ; ---------------------------------------------------------------------------
.text:00401436
.text:00401436 loc_401436: [/color]                            ; CODE XREF: _main+8Ej
.text:00401436                mov     [esp+0A8h+var_A4], offset aHello ; "Hello\n"
.text:0040143E                 mov     [esp+0A8h+var_A8], offset dword_4433C0
.text:00401445                 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
.text:0040144A                 jmp     short loc_401456
.text:0040144C ; ---------------------------------------------------------------------------
.text:0040144C
.text:0040144C loc_40144C:                            ; CODE XREF: _main+A4j
.text:0040144C                 lea     eax, [ebp+var_C]
.text:0040144F                 inc     dword ptr [eax]
.text:00401451                 jmp     loc_4013CA
.text:00401456 ; ---------------------------------------------------------------------------
.text:00401456
.text:00401456 loc_401456:                             ; CODE XREF: _main+3Ej
.text:00401456                                         ; _main+BAj
.text:00401456                mov     [esp+0A8h+var_A8], offset aPause ; "pause"
.text:0040145D                 call    system
.text:00401462                 mov     eax, 0
.text:00401467                 leave
.text:00401468                 retn
.text:00401468 _main

Password đã lộ diện. Chính tác giả đã đưa password của mình vào data session nên ta có thể thấy ngay.
Bây giờ trong C++ có một cách để "giấu" password này đi. Có nghĩa là ta sẽ không cất nó vào data session mặc định nữa mà sẽ chỉ ra vị trí do ta chọn để cất pass này đi.
Code:
int count=0;
// Từ đây , mọi biến khởi tảo
// được đặt trong .kpnc session
#pragma data_seg (."kpnc")

char passwd[ ]=PASSWORD;
#pragma data_seg ()
// Từ đây, tất cả các biến khởi tạo
// được đặt trong session mặc định (tức., ."data").
char buff [PASSWORD_SIZE]=" ";
...
if (strcmp(&buff[0] , &passwd[0]))
...

Bây giờ, biên dịch rồi dùng IDA sẽ thấy đoạn code bắt đầu từ .text:00401406 ở trên trở thành:
Code:
.text:0040142E                 lea     edx, [ebp-98h]
.text:00401434                 mov     [esp+0B8h+var_B4], eax
.text:00401438                 mov     [esp+0B8h+var_B8], edx

Nhiệm vụ bây giờ của ta là làm sao để thấy được password:
Có thể dùng trình dumpbin trong Visual Studio để truy xuất dữ liệu từ một session mà ta chỉ định, lúc này:
dumpbin /SECTION:.kpnc /RAWDATA password.exe 

Sẽ cho ta thấy dữ liệu trong session .kpnc , nơi chứa password của ta.

Về mặc định, mỗi file .exe sẽ có một bảng các session như sau:
Code:
SECTION TABLE
01 .text     
	VirtSize: 	0003DA20h  VirtAddr:      	00001000h
	raw data offs:   	00000400h  raw data size: 	0003DC00h
	relocation offs: 	00000000h  relocations:   	00000000h
	line # offs:     	00000000h  line #'s:      	00000000h
	characteristics: 	60000060h
	CODE  INITIALIZED_DATA  EXECUTE  READ  ALIGN_DEFAULT(16)  
02 .data     
	VirtSize: 	00000190h  VirtAddr:      	0003F000h
	raw data offs:   	0003E000h  raw data size: 	00000200h
	relocation offs: 	00000000h  relocations:   	00000000h
	line # offs:     	00000000h  line #'s:      	00000000h
	characteristics: 	C0000040h
	INITIALIZED_DATA  READ  WRITE  ALIGN_DEFAULT(16)  
03 .rdata    
	VirtSize: 	00002680h  VirtAddr:      	00040000h
	raw data offs:   	0003E200h  raw data size: 	00002800h
	relocation offs: 	00000000h  relocations:   	00000000h
	line # offs:     	00000000h  line #'s:      	00000000h
	characteristics: 	40000040h
	INITIALIZED_DATA  READ  ALIGN_DEFAULT(16)  
04 .bss      
	VirtSize: 	00004BE0h  VirtAddr:      	00043000h
	raw data offs:   	00000000h  raw data size: 	00000000h
	relocation offs: 	00000000h  relocations:   	00000000h
	line # offs:     	00000000h  line #'s:      	00000000h
	characteristics: 	C0000080h
	UNINITIALIZED_DATA  READ  WRITE  ALIGN_DEFAULT(16)

Trong đó: .bss : chứa dữ liệu chưa được khởi tạo
.data: chứa dữ liệu mặc định
.rdata: dịch vụ RTL cho dữ liệu
.text: chứa code chương trình

[Up] [Print Copy]
  [Question]   Re: .:Hack Windows:. 02/02/2008 08:57:07 (+0700) | #38 | 113319
TQN
Elite Member

[Minus]    0    [Plus]
Joined: 29/06/2006 22:28:01
Messages: 888
Location: Biết làm chi ?
Offline
[Profile] [PM] [WWW] [Yahoo!]
Tui chả hiểu gì cả, code ASM của MingGW sinh ra mà lại có VC trong đây, password chổ nào cũng chả thấy, các section đó đâu phải defaul, mong Reversing chỉ giúp cho cái đầu già ăn nhậu của tui biết cái !?
[Up] [Print Copy]
  [Question]   Re: .:Hack Windows:. 02/02/2008 10:05:03 (+0700) | #39 | 113330
Reversing...
Member

[Minus]    0    [Plus]
Joined: 31/12/2007 06:28:04
Messages: 117
Location: -1.-1.-1.-1
Offline
[Profile] [PM] [Yahoo!]
À, vậy là bác hiểu rõ rồi đấy chứ . Cái code trên viết trên Dev chứ không phải VC smilie. Pass kô thấy thì chắc phải dump hết bộ nhớ rồi. Tui thấy pw: mypassword nó nằm ở vị trí này.
Code:
.kpnc:0041B000 ; Segment type: Pure data
.kpnc:0041B000 ; Segment permissions: Read/Write
.kpnc:0041B000 _kpnc           segment para public 'DATA' use32
.kpnc:0041B000                 assume cs:_kpnc
.kpnc:0041B000                 ;org 41B000h
.kpnc:0041B000 ; char passwd[]
.kpnc:0041B000 passwd          db 'mypassword',0       ; DATA XREF: main+6Eo
.kpnc:0041B00B                 align 200h
.kpnc:0041B00B _kpnc           ends

Lưu ý nữa là ở đoạn code trên phải sửa chỗ #pragma thành thế này mới thấy được:
Code:
#include <iostream>
#include <string>
using namespace std;


#define PASSWORD_SIZE 100
#define PASSWORD "mypassword"
#pragma data_seg (".kpnc")
     char passwd[ ]=PASSWORD;
#pragma data_seg ()
int main()
{...}


Còn mấy khái niệm kia thì đôi lúc mình phán thử xem sao: thấy nó thường gặp thế mà smilie
[Up] [Print Copy]
  [Question]   Debug 16/02/2008 05:35:47 (+0700) | #40 | 114862
Reversing...
Member

[Minus]    0    [Plus]
Joined: 31/12/2007 06:28:04
Messages: 117
Location: -1.-1.-1.-1
Offline
[Profile] [PM] [Yahoo!]

Bước 1: Tạo file s1.txt có nội dung sau:
Code:
n s1.bin
r cx
200
f 0 l 200 0
e 0 'MZ'
e 3C 40
e 40 'PE'
e 44 4C 01
a 46
db 03 00

a 54
db e0 00
db 0F 01
db 0B 01

a 68
db 00 10 00 00

a 74
db 00 00 40 00
db 00 10 00 00 
db 00 02 00 00
db 04 00

a 88
db 04 00

a 90
db 00 40 00 00
db 00 02 00 00 

a 9C
db 02 00 

a A0
db 00 00 10 00
db 00 10 00 00
db 00 00 10 00
db 00 10 00 00

a B4
db 10 00 00 00

a 138
db '.code' 0 0 0
db 00 10 00 00
db 00 10 00 00
db 00 02 00 00
db 00 02 00 00
db 0 0 0 0 0 0 0 0 0 0 0 0
db 20 00 00 60
db '.rdata' 0 0
db 00 10 00 00
db 00 20 00 00
db 00 02 00 00
db 00 04 00 00
db 0 0 0 0 0 0 0 0 0 0 0 0
db 40 00 00 40
db '.data' 0 0 0
db 00 10 00 00
db 00 30 00 00
db 00 02 00 00
db 00 06 00 00
db 0 0 0 0 0 0 0 0 0 0 0 0
db 40 00 00 C0

m 0 l 200 100
w
q


Bước 2: tạo file s2.txt có nội dung sau:
Code:
n s2.bin
r cx
200
f 100 l 200 0
e 100 eb fe
w
q


Bước 3: tạo file s3.txt có nội dung sau:
Code:
n s3.bin
r cx
200
f 100 l 200 0
w
q


Bước 4: tạo file make.bat có nội dung sau:
Code:
@echo off
debug < s1.txt > report.lst
debug < s2.txt >> report.lst
debug < s3.txt >> report.lst
copy /b s1.bin+s2.bin+s3.bin+s3.bin pe.exe


Bước 5: Để tất cả các file trong cùng một thư mục, rồi chạy file make.bat ở trên.
Úm ba la xì bùa..
[Up] [Print Copy]
[digg] [delicious] [google] [yahoo] [technorati] [reddit] [stumbleupon]
Go to: 
 Users currently in here 
1 Anonymous

Powered by JForum - Extended by HVAOnline
 hvaonline.net  |  hvaforum.net  |  hvazone.net  |  hvanews.net  |  vnhacker.org
1999 - 2013 © v2012|0504|218|