Thứ Ba, 20 tháng 8, 2013

Data Encryption Standard (DES)

Data Encryption Standard (DES)  là một block cipher phổ biến nhất 30 năm trong quá khứ. Mặc dù ngày nay nó không được đề cao về tính bảo mật bởi vì không gian key của DES là quá nhỏ, nó vẫn còn được sử dụng trong các ứng dụng mang tính kế thừa. Hơn nữa, mã hóa dữ liệu 3 lần trong một hàng với DES - một quá trình được biết đến như 3DES hoặc triple DES - sản sinh ra một cipher cực kì secure và được sử dụng rộng rãi ngày nay. DES là một giải thuật đối xứng được dùng để học tốt nhất, thiết kế của nó truyền cảm hứng cho nhiều ciphers hiện hành.

1. Giới thiệu về DES

Năm 1972 một cuộc cách mạng nhỏ được nổ ra bởi US National Bureau of Standards (NBS), bây giờ được gọi là National Institue of Standards and Technology (NIST): NBS đã bắt đầu một yêu cầu cho các đề xuất cho một cipher chuẩn trong nước Mỹ. Ý tưởng là tìm một secure crytographic algorithm, những gì được sử dụng cho các ứng dụng khác nhau. Cho đến thời điểm đó chính phủ luôn luôn nghĩ về crytpgraphy, và trong crytanalysis. Tuy nhiên, những năm đầu của thập kỷ 70 nhu cầu cho mã hóa cho các ứng dụng thương mại ví dụ như ngân hàng đã trở nên bức thiết mà không thể bị lờ đi được nữa.

NBS nhận được đề xuất đầy hứa hẹn trong năm 1974 từ đội mật mã làm việc tại IBM. Giải thuật IBM đưa ra dựa trên mật mã Lucifer. Lucifer là một họ của ciphers được phát triển bởi Horst Feistel vào cuối năm 1960, và là một trong những instances đầu tiên của block ciphers hoạt động trên digital data. Lucifer là một Feistel cipher những gì mã hóa các khối 64 bits sử dụng kích thước key là 128 bits. Để nghiên cứu thêm về độ bảo mật của các ciphers được đưa ra , NBS yêu cầu sự giúp đỡ của National Security Agency (NSA) . Dường như NSA chịu ảnh hưởng bởi cipher này, những gì được đặt tên là DES. Một trong những sự thay đổi đã diễn ra là DES được thiết kế chuyên biệt để chịu được các crytanalysis khác nhau, không có một cuộc tấn công nào cho đến năm 1990. Không rõ là chính IBM team  phát triển kiến thức về crytanalysis khác nhau hay là được hướng dẫn bởi NSA. Một cáo buộc, NSA còn thuyết phục IBM giảm chiều dài của Lucifer key từ 128 bit xuống 56 bit, điều này làm cho cipher có nhiều lỗ hổng với brute-force attacks.

Năm 1977, cuối cùng NBS released tất cả các chi tiết kĩ thuật của modified IBM cipher. Mặc dù cipher này được mô tả tới mức độ bit trong chuẩn, nhưng các tiêu chí của cipher, nhất là sự lựa chọn substitution boxes, đã không bao giờ được released.

Với sự phát triển nhanh chóng của các máy tính cá nhân đầu những năm 80 và tất cả các chi tiết kĩ thuật của DES được công bố, ta dễ dàng phân tích cấu trúc bên trong của cipher. Trong suốt thời kì này, các cộng đồng nghiêm cứu mật mã dân sự đã phát triển và DES đã trải qua những sự giám sát. Tuy nhiên, không có các điểm yếu nghiêm trọng nào được tìm thấy cho đến năm 1990. DES chỉ được chuẩn hóa trong 10 năm, cho đến năm 1987 . Bởi vì sự sử dụng rộng rãi của DES và có những vấn đề về bảo mật, NIST đã xác nhận lại việc sử dụng cipher cho tới năm 1999, khi cuối cùng nó được thay thế bởi Advanced Encryption Standard (AES).

Thứ Năm, 15 tháng 8, 2013

Thiết lập một Server và Client đơn giản sử dụng Stream Sockets

Bước thứ nhất: Tạo một ServerSocket

Thiết lập một server đơn giản yêu cầu 5 bước  . Bước 1 là tạo một ServerSocket object. Một lời gọi tới ServerSocket constructor, ví dụ như

    ServerSocket server = new ServerSocket( portNumber, queueLength);

đăng ký môt TCP port number  có sẵn và chỉ rõ số lượng clients cực đại có thể chờ để kết nối đến server (ví dụ như, queue length) . Port number được sử dụng bởi client để xác định vị trí của ứng dụng server trên máy server. Nó thường được gọi là handsharke point. Nếu queue bị đầy, server sẽ từ chối các kết nối của client. Constructor thiết lập port nơi server chờ các kết nối đến từ clients -- một quá trình được biết đến như là binding the server to the port. Mỗi client sẽ yêu cầu để kết nối đến server trên port này. Duy nhất một ứng dụng tại một thời điểm có thể được gán để một port xác định trên server.

Note: Port numbers có thể nằm giữa 0 và 65,535. Hầu hết các hệ điều hành dành riêng các port được đánh số nhỏ hơn 1024 cho các dịch vụ hệ thống (ví dụ, email và World Wide Web servers). Nói chung, những port dưới 1024 không được xác định như là các ports kết nối trong các chương trình người dùng. Thực tế, một vài hệ điều hành yêu cầu các đặc quyền truy nhập đặc biệt để gán các chỉ số port dưới 1024.

Bước 2: Chờ đợi một kết nối

Các chương trình quản lý mỗi kết nối client với một Socket object. Trong Bước 2, server lắng nghe một cách không giới hạn (hoặc các khối) cho một nỗ lực kết nối đến từ client. Để lắng nghe một kết nối client, chương trình gọi phương thức accept từ ServerSocket, như sau:

    Socket connection = server.accept();

sau khi thực hiện dòng lệnh phía trên ta thu được kết quả là một Socket khi một kết nối với một client được thiết lập. Socket này cho phép server tương tác với client. Những sự tương tác với client thực sự diễn ra tại một server port khác với handshake point. Nó cho phép port được chỉ định trong Bước 1 được sử dụng lại trong một server đa luồng để chấp nhận một kết nối client khác.

Bước 3: Lấy I/O Streams của Socket
Bước 3 là lấy OutputStream  và InputStream objects để giúp server giao tiếp với client bằng các hành động như gửi và nhận bytes. Server gửi thông tin tới client thông qua một OutputStream và nhận thông tin từ client thông qua một InputStream. Server gọi phương thức getOutputStream trên socket để có được một tham chiếu tới OutputStream của Socket và gọi phương thức getInputStream trên Socket để có được một tham chiếu tới InputStream của Socket 

Stream objects có thể được sử dụng để gửi hoặc là nhận từng bytes hoặc một chuỗi bytes với phương thức write của OutputStream và phương thức read của InputStream tương ứng. Thông thường, sẽ là hữu dụng để gửi và nhận các giá trị của các kiêu nguyên thủy (ví dụ, int double) hoặc Serializable objects (ví dụ, Strings hoặc các kiểu serializable khác) hơn là gửi bytes. Chúng ta sử dụng các kiểu stream khác (ví dụ như ObjectOutputStream và ObjectInputStream) xung quanh OutputStream InputStream kết hợp với Socket. Ví dụ,

    ObjectInputStream input = 
         new ObjectInputStream( connection.getInputStream() );

    ObjectOutputStream output = 
         new ObjectOutputStream( connection.getOutputStream() );

Vẻ đẹp trong việc thiết lập các mối quan hệ như trên đó là bất cứ thứ gì server writes tới ObjectOutputStream  được gửi thông qua OutputStream và là available tại InputStream của client, và bất cứ thứ gì client writes tới OutputStream của nó (với một ObjectOutputStream tương ứng) là available với InputStream phía server.

Bước 4: Thông hiện việc xử lý
Bước 4 là một chặng xử lý, xử lý những gì mà server và client giao tiếp thông qua OutputStream InputStream objects.

Bước 5: Đóng kết nối 
Trong Bước 5, khi việc truyền dữ liệu giữa hai bên hoàn tất, server đóng kết nối thông qua việc gọi phương thức close trên các streams và trên Socket.


Thiết Lập Một Client Đơn Giản Sử Dụng Stream Sockets

Thiết lập một client đơn giản trong Java yêu cầu 4 bước.

Bước 1: Tạo một Socket để kết nối tới Server
Trong Bước 1, chúng ta tạo một Socket để kết nối đến server. Socket constructor thiết lập kết nối. Cho ví dụ, statement sau:

    Socket connection = new Socket( serverAddress, port);

sử dụn Socket constructor với 2 arguments  --- Địa chỉ của server (serverAddress) và port number. Nếu việc kết nối là thành công, statement này sẽ trả về một Socket. Một nỗ lực kết nối thất bại có thể ném ra một thể hiện (instance) cả subclass của IOException., vì vậy nhiều chương trình đơn giản bắt IOException. Một UnknownHostException xảy ra hệ thống không thể được server name được chỉ định trong một lời gọi tới Socket constructor tới một địa chỉ IP tương ứng.

Bước 2: Lấy I/O Streams của Socket
Trong Bước 2, client sử dụng các phương thức getInputStream getOutputStream của Socket để có được các tham chiếu tới InputStream OutputStream của Socket. Cũng như trong bước 2 đối với phía server, chúng ta có thể sử dụng các kĩ thuật với các kiểu stream khác xung quanh InputStream OutputStream được kết hợp với Socket. Nếu server đang gửi thông tin trong dạng của các kiểu thực sự, client nên nhận thông tin trong cùng một định dạng. Do vậy, nếu server gửi các giá trị với ObjectOutputStream , client nên đọc các giá trị này với ObjectInputStream. 

Bước 3: Thực hiện việc xử lý
Bước 3 là một chặng xử lý các dữ liệu trong giao tiếp giữa client và server thông qua InputStream OutputStream objects.

Bước 4: Đóng kết nối
Trong Bước 4, client đóng kết nối khi việc trao đổi dữ liệu hoàn tất thông qua việc gọi phương thức close trên các streams và trên Socket. Client phải xác định khi nào server hoàn tất việc gửi thông tin vì vậy nó có thể gọi close để đóng kết nối Socket. Cho ví dụ, phương thức read của  InputStream trả về giá trị -1 khi nó tìm thấy end-of-stream (còn được gọi là EOF - end of file). Nếu một ObjectInputStream đọc thông tin từ server, một EOFException xảy ra khi client cố gắng đọc một giá trị từ một stream những gì end-of-stream được phát hiện.

Thứ Ba, 13 tháng 8, 2013

Shared Service Processes

Running mọi service trong các process của chúng thay vì có services chia sẻ cùng một process bất cứ khi nào có thể sẽ gây lãng phí tài nguyên hệ thống. Tuy nhiên, trong các processes được chia sẻ nếu có bất cứ một service trong process có một lỗi gây cho process exit, tất cả services trong process sẽ kết thúc.

Một số Windows built-in services run trong process của riêng chúng và một số chia sẻ một process với các services khác. Cho ví dụ, SCM process hosts Event Log service và user-mode Plug and Play service, và LSASS process chứa các dịch vụ liên quan đến security - ví dụ như Security Accounts Manager (Samss) service, Net Logon (Netlogon) service, và IPSec Policy Agent (PolicyAgent) service.

Cũng có một process chung có tên là Service Host (SvcHost - \Windows\System32\Svchost.exe) để chứa nhiều services. Services mà run trong các SvcHost processes bao gồm Telephony (TapiSrv), Remote Procedure Call (RpcSs), và Remote Access Connection Manager (Rasman). Windows implements services mà run trong SvcHost như là các Dlls và includes một ImagePath giống như là “%SystemRoot%\System32\svchost.exe -k netsvcs” trong service registry key. Registry key của service phải có một registry value có tên là ServiceDll dưới Parameters subkey mà trỏ tới file Dll của service.

Tất cả các services chia sẻ một SvcHost process chỉ định cùng một parameter (ví dụ như "-k netsvcs") vì vậy chúng có một single entry trong SCM's image database.

Thứ Bảy, 10 tháng 8, 2013

Service Control Manager (SCM)

Như chúng ta đã biết "Services" trên Windows có thể được biết đến hoặc như là server process hoặc divice driver, bài viết này nhắc đến services trên khía cạnh là user-mode processes. Services giống như là UNIX "daemon processes" hoặc VMS "detached processes" ở điểm là chúng có thể được cấu hình để start một cách tự động vào thời điểm system boot mà không yêu cầu một tương tác đăng nhập. Chúng còn có thể được start một cách thủ công (ví dụ như running Services administrative tool hoặc thông qua việc gọi hàm StartService). Thông thường, services không tương tác với user được đăng nhập, mặc dù cũng có những điều kiện đặc biệt khi nó có thể.

Service control manager (SCM) là một system process đặc biệt running image \Windows\System32\Services.exe , nó chịu trách nhiệm cho việc starting, stopping, và interacting với service processes. Service program chỉ là Windows images mà gọi các Windows functions đặc biệt để tương tác với SCM nhằm thực hiện những kiểu công việc như là đăng ký startup của service, hồi đáp tới status requests, tạm ngưng hoặc shutting down service. Các tài liệu về subkeys và values cho services được document trong resource kit Registry Entries help file (Regentry.chm).

Luôn nhớ một điều là services có 3 cái tên : process name bạn nhìn thấy running trên hệ thống, internal name trong registry, và display name được hiển thị trong Services administartive tool. (Không phải mọi services đều có display name - Nếu một service không có một display name , internal name được hiển thị). Với Windows, services còn có thể có một description field hiển thị chi tiết hơn những gì service làm.

Một số Windows components được implemented như services , ví dụ như Spooler, Event Log, Task Scheduler, và các thành phần networking.

Services

Service

Hầu hết mọi hệ điều hành đều có một cơ chế để start processes tại system startup time để cung cấp services không phụ thuộc vào một interactive user. Trong Windows, những processes như vậy được gọi là services hoặc Windows services , bởi vì chúng dựa trên Windows API để tương tác với hệ thống. Services tương tự như Unix daemon processes và thường implement server side của các ứng dụng client/server. Một ví dụ của một Windows service có thể là một Web server bởi vì nó phải running mà không quan tâm đến có hay không một ai đó được logged on vào máy tính và nó phải start running khi hệ thống starts vì vậy một nhà quản trị không phải nhớ để start nó.

Windows services bao gồm 3 thành phần: một ứng dụng dịch vụ, một chương trình điều khiển ứng dụng (a service control program) SCP, và một trình quản lý điều khiển ứng dụng (the service control manager) SCM. Thứ nhất, chúng ta sẽ mô tả service applications, service accounts, và các hoạt động của SCM. Sau đó chúng tôi sẽ giải thích cách auto-start services được started trong suốt system boot.
Hầu hết mọi OS có một cơ chế để start các processes tại thời điểm hệ thống khởi động để cung cấp services mà không bị bó buộc vào một người dùng tương tác. Trong Windows, những processes như vậy được gọi là services hoặc Windows services , bởi vì chúng dựa trên Windows API để tương tác với hệ thống. Services trong Windows tương tự như UNIX daemon processes và thường implement phía bên server của các ứng dụng client/server. Một ví dụ của Windows service có thể là Web server, lí do là vì nó phải running bất kể khi có hay không một ai đó đăng nhập vào máy tính và nó phải running khi hệ thống khởi động vì vậy người quản trị viên không phải nhớ là mình phải khởi động nó. 

Windows services bao gồm 3 thành phần: một ứng dụng dịch vụ (a service application), một chương trình điều khiển ứng dụng (a service control program), và một trình quản lý điều khiển ứng dụng (the service control manager). Đầu tiên, chúng ta sẽ mô tả service applications, service accounts, và các hoạt động của SCM. Sau đó, chúng tôi sẽ giải thích cách auto-start services được khởi động trong suốt system boot. Chúng tôi sẽ còn cover các bước SCM thực hiện khi một service bị lỗi trong quá trình khởi động của nó và cách SCM shuts down services. 

Service Applications

Service applications, ví dụ như Web servers, gồm ít nhất một excutable để run như là một Windows service. Một người dùng muốn start, stop, hoặc cấu hình (configure) một service sử dụng một SCP. Mặc dù Windows cung cấp built-in SCPs phục vụ cho việc start, stop, pause, hoặc tiếp tục chức năng, một vài service applications có những SCP của riêng họ để cho phép các nhà quản trị để xác định các thiết lập cấu hình đến riêng dịch vụ chúng quản lý. 

Service applications đơn giản là Windows executables (GUI hoặc console) thêm vào đó là đoạn mã bổ sung để nhận commands từ SCM cũng như là giao tiếp với SCM thông qua các trạng thái ứng dụng. Bởi vì hầu hết dịch vụ không có một user interface, chúng được xây dựng như là console programs. 

Khi bạn install một ứng dụng bao gồm một service, chương trình cài đặt ứng dụng phải register service với hệ thống. Để register service, setup program gọi hàm CreateService, một hàm liên quan đến các dịch vụ được implemented trond Advapi32.dll (\Windows\System32\Advapi32.dll). Advapi32 , the "Advance API" DLL, implement tất cả SCM APIs phía client. 

Khi một setup program registers một service thông qua việc gọi CreateService, một message được gửi tới SCM trên máy đặt service. SCM sau đó tạo một registry key cho service dưới HKLM\SYSTEM\CurrentControlSet\Service. Từng keys cho mỗi dịch vụ định nghĩa path đến excutable image chứa service cũng như là parameters và configuration options. 

Sau khi tạo một service, các ứng dụng cài đặt hoặc quản lý có thể start service thông qua hàm StartService . Bởi vì một vài ứng dụng dựa trên dịch vụ còn phải khởi tạo trong suốt boot process đến function, ta không thường thấy một setup program register một service như là một auto-start service, yêu cầu user reboot hệ thống để hoàn tất việc cài đặt, và để cho SCM start service như là system boots. 

Khi một chương trình gọi CreateService , nó phải xác định một số lượng parameters mô tả các đặc tính của service. Các thuộc tính bao gồm kiểu service (có phải service đó run trong process của riêng nó hay là run trong một process được chia sẻ giữa nhiều services), vị trí của service's excutable image file, một optional display name, một optional account name và password được sử dụng để start service khi trong một account's security context, một start type chỉ ra rằng service starts tự động khi hệ thống boot hay là thực hiện thủ công dưới sự điều hướng của một SCP, một error code ám chỉ cách hệ thống phản ứng nếu service phát hiện một lỗi khi starting, và, nếu service starts tự động , optional information sẽ xác định khi nào service starts liên quan đến services khác.


SCM lưu mỗi thuộc tính như là một giá trị trong registry key của dịch vụ. Figure 4-8 shows một ví dụ của một service registry key. 

 Nếu một service cần lưu thông tin cấu hình có tính chất riêng tư với service, theo quy tắc thì ta tạo ra một subkey có tên là Parameter dưới service key của nó và sau đó lưu thông tin cấu hình trong các giá trị dưới subkey đó. Service sau đó có thể lấy được các giá trị này bằng cách sử dụng các hàm registry chuẩn. 


Note: SCM không access đến Parameters subkey của service cho đến khi service được xóa đi, tại thời điểm mà SCM xóa đi trọn vẹn key của service, bao gồm cả subkeys giống như Parameters.

Chúng ta cùng nhau phân tích một vài thông số :

Start :
- SERVICE_BOOT_START (0): Ntldr hoặc Osloader nạp trước driver vì vậy nó nằm trong bộ nhớ trong suốt quá trình boot. Các driver này được khởi tạo trước SERVICE_SYSTEM_START drivers.
- SERVICE_SYSTEM_START (1): drivers nạp và được khởi tạo trong suốt quá trình khởi tạo kernel sau khi SERVICE_BOOT_START được khởi tạo. 
- SERVICE_AUTO_START (2) : SCM starts driver hoặc service sau SCM process, Service.exe, starts. 
- SERVICE_DEMAND_START (3) : SCM starts driver hoặc service theo nhu cầu.
- SERVICE_DISABLED (4) : driver hoặc service không được nạp hoặc khởi tạo

Type:
- SERVICE_KERNEL_DRIVER (1) : Device driver
- SERVICE_FILE_SYSTEM_DRIVER (2) : Kernel-mode file system driver
- SERVICE_ADAPTER (4) : Lỗi thời
- SERVICE_RECOGNIZER_DRIVER (8) : File system recognizer driver
- SERVICE_WIN32_OWN_PROCESS (16): Service runs trong một process mà hosts chỉ một service
- SERVICE_WIN32_SHARE_PROCESS (32): Service runs trong một process mà hosts nhiều services. 
- SERVICE_INTERACTIVE_PROCESS (256) : Service được phép hiển thị windows trên console và nhận user input. 

Để ý vào Type values có 3 giá trị được áp dụng cho device drivers: device driver, file system driver, và file system recognizer. Các giá trị này được sử dụng bởi Windows device drivers, những gì còn lưu các parameters của chúng như là registry data trong Service registry key. SCM chịu trách nhiệm starting drivers với Start value là SERVICE_AUTO_START hoặc SERVICE_DEMAND_START, vì vậy SCM database có bao gồm drivers. Service sử dụng các kiểu khác, SERVICE_WIN32_OWN_PROCESS và SERVICE_WIN32_SHARE_PROCESS. Một excutable mà hosts nhiều hơn một service xác định SERVICE_WIN32_SHARE_PROCESS . Một lợi thế khi có một process run nhiều hơn một service đó là system resources có thể được tiết kiệm so với việc run chúng trong nhiều process. Một bất lợi tiềm ẩn đó là nếu một trong các services đang running trong cùng một process bị lỗi mà kết thúc process, tất cả services của process cũng kết thúc. Còn nữa, tất cả services phải run dưới cùng một account. 

Khi SCM starts một service process , process ngây lập tức gọi StartServiceCtrlDispatcher function . StartServiceCtrlDispatcher accepts một danh sách entry points bên trong services, một entry point cho mỗi service trong process. Mỗi entry point được nhận dạng bởi tên của service mà entry point tương ứng với. Sau khi tạo ra một kết nối đến SCM, StartServiceCtrlDispatcher  đứng trong một loop đợi commands thông qua kết nối đến từ SCM. SCM gửi một service-start command mỗi lần nó start một service process sở hữu. Đối với mỗi lần nhận start command, StartServiceCtrlDispatcher function tạo một thread, được gọi là service thread, để gọi starting service's entry point và implement command loop cho service. StartServiceCtrlDispatcher chờ vô thời hạn cho commands từ SCM và trả quyền điều khiển đến process's main function chỉ khi process's services dừng lại, cho phép service process dọn dẹp resources trước khi thoát. 

Hành động đầu tiên của một service entry point đó là gọi hàm RegisterServiceHandler . Hàm này nhận và lưu một con trỏ đến một hàm, được gọi là control handler, những gì mà service implements nhiều commands nó nhận tử SCM. RegisterServiceHandler không giao tiếp với SCM, nhưng nó lưu hàm trong local process memory cho hàm StartServiceCtrlDispatcher . Service entry point tiếp tục khởi tạo service, những gì bao gồm cấp phát bộ nhớ, tạo ra các điểm đầu cuối giao tiếp, và đọc các thông tin cấu hình cá nhân tử registry. Một quy tắc mà hầu hết services tuân theo là lưu parameters của chúng dưới một subkey của service registry key của chúng , có tên là Parameters. Trong khi entry point đang khởi tạo service , nó có thể gửi status messages một cách định kỳ , sử dụng hàm SetServiceStatus , để SCM chỉ ra cách khởi động service. Sau khi entry point hoàn thành việc khởi tạo, một service thread thường đứng trong loop chờ cho requests từ client applications. Cho ví dụ, một Web server có thể khởi tạo một TCP listen socket và chờ inbound HTTP connection requests. 

Một service process's main thread, những gì thực thi trong hàm StartServiceCtrlDispatcher , nhận SCM commands trực tiếp tại services trong process và gọi target service's control handler function (được lưu trong RegisterServiceHandler). SCM commands bao gồm stop, pause, resume, interrogate, và shutdown , hoặc application-defined commands. 

Thứ Sáu, 2 tháng 8, 2013

Integer Arithmetic in ASM

Introduction

Assembly language có các lệnh để di chuyển bits vòng quanh bên trong operands. Shift và rotate instructions, các lệnh này hữu ích khi điều khiển các thiết bị phần cứng, mã hóa dữ liệu, và implementing high-speed graphics. Bài viết này giải thích cách thực hiện shift và rotate operations và làm thế nào để thực hiện các phép tính nhân chia sử dụng shift operations.

Tiếp theo chúng ta sẽ tìm hiểu các lệnh nhân chia đối với số nguyên. Intel phân loại các lệnh theo các phép tính có dấu và không dấu. Sử dụng những lệnh này, chúng tôi show cách làm thế nào để chuyển mathematical expressions từ C++ vào trong assembly language. Compilers chia các expressions phức tạp thành một chuỗi các lệnh máy rời rạc. Nếu bạn học cách translate các phép tính toán trong assembly language , bạn có thể hiểu hơn về cách compilers làm việc, và bạn sẽ có thể optimize assembly language. Bạn sẽ học về cách các luật ưu tiên và register optimization làm việc tại mức độ mã máy.

Các phép tính với các số nguyên có độ dài tùy ý (còn được biết đến như bignums) không được hỗ trợ bởi tất cả các ngôn ngữ bậc cao. Nhưng trong assembly language , bạn có thể sử dụng các lệnh như ADC (add with carry) và SBB (subtract with borrow) để làm việc với các số nguyên với bất kì kích thước nào. Trong loạt bài viết , tôi sẽ còn trình bày các lệnh chuyên biệt để thực hiện các phép tính trên packed decimal integers và integer strings.

Shift and Rotate Instructions

Shifting nghĩa là di chuyển các bit sang bên phải và trái bên trong một operand. Bảng dưới đây là một tập hợp các lệnh mà x86 cung cấp để di chuyển các bits, tất cả ảnh hưởng đến cờ OF và CF.

Logical Shifts and Arithmetic Shifts

Có hai cách để shift các bits của một operand. Thứ nhất, logical shift, lấp vị trí mới được tạo ra với zero. Minh họa dưới đây, một byte được dịch qua phải một vị trí. Hãy nói cách khác, mỗi bit được di chuyển đến vị trí bit thấp hơn tiếp theo. Chú ý rằng bit 7 được gán bằng 0:
Minh họa phía dưới shows một single logical right shift trên một giá trị nhị phân 11001111, kết quả là 01100111. Bit thấp nhất được dịch vào trong cờ CF:

Một kiểu shift khác được gọi là arithmetic shift. Vị trí mới được tạo được lấp với một bản sao của bit dấu của số ban đầu:


Ví dụ binary 11001111, có bit dấu là 1. Khi thực hiện shifted arthimetically 1 bit qua phải, nó trở thành 11100111
SHL Instruction

SHL (shift left) instruction thực hiện một logical left shift trên destination operand, lấp bit thấp nhất với số 0. Bit cao nhất được chuyển vào CF :

Nếu như bạn shift 11001111 sang trái 1 bit , nó trở thành:

Operand đầu tiên trong SHL là destination  và operand thứ 2 là shift count:

SHL    destination, count 

Danh sách dưới đây liệt kê các kiểu operands được cho phép bởi lệnh này:

SHL   reg, imm8
SHL  mem, imm8
SHL  reg, CL
SHL  mem, CL

x86 processors cho phép imm8 là bất kì số nguyên nào trong khoảng từ 0 đến 255. CL register cso thể chứa một shift count. Formats này còn được áp dụng cho SHR, SAL, SAR, ROR, ROL, RCR, và RCL instructions. 

Ví dụ  Trong các lệnh dưới đây , BL được shifted qua trái 1 đơn vị. Bit cao nhất được copy vào trong CF và bit thấp nhất được gán bằng 0. 

mov  bl, 8Fh                              ; BL = 10001111b
shl    bl, 1                                  ; BL = 00011110b, CF = 1

Multiple Shifts  Khi một giá trị được shifted qua trái nhiều lần, CF chứa bit cuối cùng đực shifted ra ngoài MSB. Trong ví dụ dưới đây, CF không giữ giá trị bit 7 mà là bit 6:

mov   al, 10000000b
shl     al, 2                                            ; al = 00000000b, CF =0

Tương tự, khi một giá trị được shifted sang phải nhiều lần, CF chứa bit cuối cùng được shifted ra ngoài LSB. 

Bitwise Multiplication SHL có thể thực hiện phép nhân cho lũy thừa của 2. Shifting bất kì operand sang trái n bits sẽ nhân operand với 2 ^ n. Cho ví dụ, shifting số 5 sang trái 1 bit sẽ cho kết quả là 5 x 2^1 = 10

Nếu binary 00001010 (decimal 10) được dịch sang trái 2 bits, kết quả sẽ giống như việc ta nhân 10 với 2^2:


SHR Instruction

SHR (shift right) instruction thực hiện một logical right shift trên destination operand, thay thế bit cao nhất với 0. Bit thấp nhất được sao chép vào trong CF, và giá trị đang có của CF bị mất đi:

SHR sử dụng cùng các định dạng lệnh như SHL. Trong ví dụ sau, 0 từ bit thấp nhất trong AL được sao chép vào trong AL, và bit cao nhất được lấp bằng zero. 

Multiple Shifts  Trong một phép toán shift nhiều lần, bit cuối cùng được shifted ngoài LSB là giá trị trong CF:

Bitwise Division   Logically shifting một unsigned integer sang phải n bits chia operand đi lũy thừa của 2. Trong statements sau, chúng ta chia 32 cho 2^1, kết quả là 16:

Trong ví dụ sau , 64 chia cho 2^3:
Phép chia các số có dấu thông qua shifting được thực hiện bằng cách sử dụng SAR instruction bởi vì nó bảo vệ bit dấu của số. 

SAL và SAR Instructions

SAL (shift arithmetic left) instruction hoạt động giống như lệnh SHL. Đối với mỗi shift count, SAL shifts mỗi bit trong destination operand sang vị trí cao nằm bên cạnh. Bit được thấp nhất được gán bằng 0. Bit cao nhất được chuyển đến CF, bit nằm trong CF bị bỏ đi:

Nếu bạn shift binary 11001111 sang trái 1 bit, nó trở thành 10011110:
SAR (shift arthimetic right) instruction thực hiện một right arithmetic shift trên destination của nó:

Operands của SAL và SAR giống như opearands của SHL và SHR. Shift có thể được lặp lại, dựa trên counter trong operand thứ 2:

SAR   destination, count

Ví dụ sau đây show cách SAR duplicates bit dấu. AL là một giá trị âm trước và sau khi nó được shifted qua phải:


Signed Division Bạn có thể chia một signed operand cho lũy thừa của 2 , sử dụng SAR instruction. Trong ví dụ sau, -128 chia cho 2^3. Kết quả là -16:

Sign-Exten AX into EAX  Giả sử AX chứa một giá trị nguyên có dấu và bạn muốn extend dấu của nó trong EAX. Thứ nhất, thứ nhất shift EAX sang trái 16 bits, sau đó shift arithmetically sang phải 16 bits.

Các kĩ thuật phân tích tĩnh malware

Việc học các kĩ thuật phân tích tĩnh là cần thiết khi mới chập chững bước vào nghề này. Phân tích tĩnh mô tả quá trình phân tích code hoặc là cấu trúc của một chương trình để xác định chức năng của nó. Chương trình bản thân nó không run khi ta phân tích tĩnh. Chúng ta run chương trình khi thực hiện các kĩ thuật phân tích động.

Bài viết này đề cập nhiều cách để lấy được những thông tin hữu ích từ excutables. Cụ thể chúng ta thảo luận về các kĩ thuật sau:

  • Sử dụng antivirus tools để xác minh tính độc hại
  • Sử dụng hashes để nhận dạng malware
  • Thu thập thông tin từ file's strings, functions, và headers
Mỗi kĩ thuật có thể cung cấp những thông tin khác nhau, và việc sử dụng những công cụ nào còn tùy thuộc vào những thông tin bạn muốn có được. Thông thường, chúng ta sẽ sử dụng một vài kĩ thuật để thu thập thông tin nhiều nhất có thể. 

Antivirus Scanning: Bước khởi đầu

Khi bạn nghi vấn một file nào đó là malware, bạn bắt đầu phân tích malware đó, đầu tiên bạn nên run nó qua nhiều antivirus programs, vì biết đâu đó một trong những av này đã nhận dạng được malware đó rồi. Nhưng antivirus tools thì không được hoàn hảo cho lắm. Chúng chủ yếu dựa trên một cơ sở dữ liệu chứa những chữ kí (signatures) được tạo ra cho malware mà đã được nhận dạng, một số AV có thể sử dụng cách nhận dạng theo hướng hành vi. Một vấn đề phát sinh đó là malware writers có thể dễ dàng chỉnh sửa code của họ, do đó làm thay đổi đi chữ kí của chương trình và qua mặt virus scanners. Còn nữa, những malware hiếm gặp không bị nhận dạng bởi antivirus software bởi vì đơn giản là nó không có trong cơ sở dữ liệu. Cuối cùng, heuristics, mặc dù có thể nhận dạng được những mã độc chưa được biết đến, vẫn có thể bị qua mặt bởi các loại malware mới hiện nay. 

Bởi vì rất nhiều loại virus hiện nay sử dụng các chữ kí và heuristics khác nhau, chúng ta có thể run một vài antivirus programs để quét qua cùng một mẫu virus. Websites như VirusTotal (virustotal.com) cho phép bạn uppload một file để quét dưới nhiều antivirus engines. VirusTotal sinh ra một bản báo cáo cho ta biết rằng có bao nhiêu AV nhận dạng file như là mã độc, tên malware, và có thể là thông tin về malware đó. 

Hashing: một dấu vân tay cho malware 

Hashing là một phương pháp được dùng để nhận dạng malware một cách duy nhất. Malicious software được run thông qua một chương trình hashing, chương trình này sinh ra một hash duy nhất dùng để nhận dạng malware (một kiểu của dấu vân tay). Message-Digest Algorithm 5 (MD5) hash function là được một cách được sử dụng cho malware analysis, mặc dù Secure Hash Algorithm 1 (SHA-1) cũng rất phổ biến. 

Cho ví dụ, việc sử dụng một chương trình có sẵn như md5deep để tính toán hash của Solitaire program (trên Windows) có thể sinh ra output như sau:


C:\>md5deep c:\WINDOWS\system32\sol.exe
373e7a863a1a345c60edb9e20ec3231 c:\WINDOWS\system32\sol.exe

Hash là 373e7a863a1a345c60edb9e20ec3231.

Có một phiên bản hỗ trợ GUI đó là WinMD5

Vậy ta khi ta có được hash của một file ta thực hiện các bước sau:
  • Sử dụng hash như là một nhãn (lable).
  • Chia sẻ hash với các nhà phân tích khác để giúp họ nhận dạng malware.
  • Tìm kiếm giá trị hash đó trên mạng nếu file đã được nhận dạng.

Finding Strings

Một string trong một chương trình là một chuỗi các kí tự ví dụ như "the.". Một chương trình chứa strings nếu nó in ra một message, kết nối đến một URL, hoặc sao chép một file đến một vị trí xác định nào đó. 

Searching qua strings có thể là một cách đơn giản để có được những gợi ý về chức năng của một chương trình. Cho ví dụ, nếu một chương trình truy nhập vào một URL, khi đó bạn sẽ nhìn thấy URL được truy nhập như là một string trong chương trình. Bạn có thể sử dụng Strings program (http://bit.ly/ic4plL) để search các strings xuất hiện trong một executable, các strings có thể được lưu trong dạng ASCII hoặc Unicode. 

Cả ASCII và Unicode formats lưu các kí tự trong một chuỗi kết thúc bằng kí tự NULL để ám chỉ rằng string kết thúc. ASCII sử dụng 1 byte cho 1 kí tự, và Unicode sử dụng 2 bytes cho 1 kí tự.

Figure 2-2 shows string BAD được lưu như ASCII. ASCII string được lưu như các bytes 0x42, 0x41, 0x44, và 0x00, trong đó 0x42 là biểu diễn ASCII của chữ in hoa B, 0x41 biểu diễn cho A, và tương tự. 0x00 ở cuối cùng là NULL terminator.


Figure 2-3 shows string BAD được lưu như Unicode
Khi Strings searches một excutable để tìm ASCII và Unicode strings, nó lờ đi context và formatting vì vậy nó có thể phân tích bất cứ kiểu file nào và phát hiện strings trong toàn bộ file. 

Luật chơi chung trong phân tích malware

Thứ nhất : Đừng đi qua sâu vào các chi tiết. Hầu hết malware programs thường lớn và phức tạp, và bạn không thể nào hiểu được mọi chi tiết. Thay vào đó hãy tập trung vào các đặc tính "khóa" . Khi bạn đi vào những phần khó và phức tạp, cố gắng để có được một cái nhìn toàn cảnh trước khi bạn bị mắc kẹt trong những đám cỏ dại.

Thứ hai, nhớ rằng các công cụ và các cách tiếp cận khác nhau được dành cho các công việc khác nhau. Không phải chỉ có một cách tiếp cận. Mọi hoàn cảnh là khác nhau, và các công cụ và các kĩ thuật khác nhau bạn sẽ học sẽ tương tự và thỉnh thoảng là "đè " lên nhau, ví dụ công cụ A có thể thực hiện chức năng của công cụ B. Nếu bạn không may mắn với công cụ này, hãy thử công cụ khác. Nếu bạn mắc kẹt quá lâu trong một vấn đề; hãy chuyển qua một thứ nào đó khác đi. Thử phân tích malware với nhiều góc nhìn khác hoặc nhiều cách tiếp cận khác.

Cuối cùng, nhớ rằng việc phân tích malware giống như ta đang chơi trò mèo vờn chuột. Khi các kĩ thuật phân tích mới được phát triển, malware authors cũng tạo ra các kĩ thuật mới để cản trở việc phân tích. Để trở thành một nhà phân tích malware thành công, bạn phải có thể nhận dạng , hiểu, và chống lại các kĩ thuật của người viết malware, và respond đối với các thay đổi.

Thứ Năm, 1 tháng 8, 2013

Các kiểu malware

Khi thực hiện phân tích malware, bạn có thể đẩy nhanh tốc độ phân tích của mình thông qua việc phỏng đoán malware đang cố gắng làm gì và sau đó xác minh được những giả thiết của mình. Dĩ nhiên, bạn sẽ có thể có được những suy đoán tốt hơn nếu bạn biết được những thứ mà malware thường làm. Sau đây là một vài dạng malware chúng ta thường gặp:

  • Backdoor. Malicious code cài đặt chính nó lên một máy tính để cho phép attacker truy nhập. Backdoors thường để cho attacker kết nối đến máy tính với rất ít hoặc là không cần phải xác thực và thực thi command trên local system. 
  • Botnet. tương tự như backdoor, nó cho phép attacker thâm nhập vào hệ thống, nhưng tất cả các máy bị lây nhiễm với cùng một botnet sẽ nhận các lệnh giống nhau từ một command-and-control server. 
  • Downloader. Malicious code tồn tại chỉ để download malicious code khác. Downloaders thường được cài đặt bởi attackers khi họ thâm nhập vào hệ thống lần đầu tiên. Downloader program sẽ download và cài đặt thêm malicious code. 
  • Information-stealing malware. Malware thường thu thập thông tin từ máy victim và gửi nó về cho attacker. Ví dụ như là sniffers, password hash grabbers, và keyloggers. Kiểu malware này thường được sử dụng để ăn trộm các thông tin riêng tư quan trọng như là tài khoản ngân hàng và địa chỉ email.
  • Launcher. Malicious program được sử dụng để launch malicious programs khác. Thường thường, launchers sử dụng các kĩ thuật không chính thống để launch malicious programs khác để truy nhập vào hệ thống một cách âm thầm lặng lẽ. 
  • Rootkit. Malicious code được thiết kế để che dấu sự tồn tại của code khác. Rootkits thường đi cặp với malware khác, ví dụ như backdoor, để cho phép truy nhập từ xa và code cũng khó bị phát hiện trên máy victim. 
  • Scareware. Malware được thiết kế để dọa user bị lây nhiễm để họ mua một thứ gì đó. Nó thường có một giao diện người dùng trông giống như một chương trình antivirus hoặc chương trình bao mật nào đó. Nó nhắc nhở users rằng có malicious code trên hệ thống của họ và các duy nhất để khắc phục sự cố đó là mua sản phầm phần mềm mà chúng sản xuất, khi thỏa thuận mua bán đã xong, atttacker chỉ cần remove scareware chứ không làm gì cả và chúng ta mất tiền oan.
  • Spam-sending malware. Malware này lây nhiễm lên máy users và sử dụng máy này để gửi spam. Kiểu malware này cũng được chuộng bởi vì nó cho phép malware author bán đi các dịch vụ gửi spam kiếm lời. 
  • Worm or virus. Malicious code có thể nhân bản chính nó và lây nhiễm rộng ra các máy tính khác. 
Malware có thể sử dụng nhiều tính năng chứ không chỉ giới hạn trong một dạng. Cho ví dụ, một chương trình có thể một keylogger để lấy passwords và một thành phần là worm để gửi spam. 

Malware có thể được phân loại dựa trên đối tượng của attacker đó là đại trà hay là một mục tiêu. Mass malware, ví dụ như scareware, được thiết kế để lây nhiễm càng nhiều máy càng tốt. Trong 2 đối tượng, nó là phổ biến, và nó thường không phức tạp cho lắm và có thể dễ dàng phát hiện và vô hiệu hóa bởi vì nó là mục tiêu của các phần mềm bảo mật.

Targeted malware, giống như backdoor, phù hợp để tấn công một tổ chức. Targeted malware thường là mối đe dọa lớn hơn mass malware, bởi vì nó không được lan đi rộng và các sản phầm bảo mật có thể sẽ không bảo vệ được bạn khỏi nó. Nếu có một phân tích chi tiết đối với targeted malware, gần như là không thể bảo vệ mạng của bạn khỏi malware và loại bỏ infections.