惡意軟體實作以及分析

資訊安全領域的研究、心得分享

2016年2月11日 星期四

WinDBG(二)

轉貼於 2016/2/11 晚上
來源網址:http://ephrain.pixnet.net/blog/post/38599264-%5Bwindbg%5D-%E8%A8%AD%E5%AE%9A-vmware-kernel-debugging

前提:
本章節主要講述WinDBG如何調適在虛擬機當中的Windows內核,當前一章所要求的工具
都下載完成後,還必須做一下設定,才能讓WinDBG調適虛擬機當中的內核。
我在網路上發現有一位博主對這裡的設定已經有了一份圖文並茂的教學,因此我就不再
自己剪貼圖文了,而是轉貼他的文章,開頭有來源網址。

正文:
Step1:
首先進入 VMWare 裡的 Windows 7, 在 cmd 命令提示環境下,先執行 bcdedit 看一下目前的開機設定, 通常在 Windows 7 環境下面只會有一個「Windows 開機載入器」:










Step 2:
執行 bcdedit /copy {current} /d "Windows 7 Kernel Debug Mode", 這行指令會複製一份目前的開機設定,並且命名為 Windows 7 Kernel Debug Mode。










 Step 3:
執行 msconfig,可以看到現在有兩個開機選項。



 Step 4:
選擇我們新加的開機選項,再選擇進階選項。 將「偵錯」打勾,選擇偵錯連接埠「COM2」後按下「確定」。 這個部分也可以選擇 COM1-4,沒有特別的限制。







Step 5:
將 Windows 7 關機。 關機完成後,選擇 VMWare > VM > Settings > Add > Serial Port。




 Step 6:
選擇「Output to name pipe



 Step 7:
選擇連線至 \\.\pipe\com_2 這個 pipe(視之前在 Windows 7 選擇的是哪個 COM 而定), 並選定「This end is the server」與「The other end is an application」後, 按下「Finish」結束新增裝置。




 Step 8:
在 VM Setting > Serial Port 的部分, 要勾選「Yield CPU on poll」,按下「OK」結束設定。




Step 9:
重新啟動 Windows 7 這個虛擬機器。 開機後會有兩個開機選項,選擇「Windows 7 Kernel Debug Mode」繼續。 通常啟用偵錯工具的話,可以注意到進入 Windows 的速度會稍慢一些...




 Step 10:
執行下面這行指令以啟動 windbg remote kernel debugging 模式 "C:\Program Files\Debugging Tools for Windows (x64)\windbg.exe" -b -k com:pipe,port=\\.\pipe\com_2,resets=0 這邊 windbg 的路徑請自行依情形修改,com_2 也要依照之前設定的 COM1-4 來設定。 如果成功的話,應該可以看到如下的畫面:



有時候 kernel debug 連接沒有成功,會看到他停在「Waiting to reconnect...」, 如果等了一下都還沒有連接上的話,可以試著重新啟動 windbg, 再不行的話就連虛擬機器也重新啟動看看,通常就可以了~~

Windbg(一)

撰寫於 2016/2/11 晚上


前提:
這篇系列文章將會對WinDBG這個軟體的操作方式進行教學。

介紹WinDBG:

WinDbgMicrosoft Windows上的多用途調試器,可從微軟網站上免費下載安裝使用。可用於調試用戶態下的應用程式驅動程序,以及核心態下的作業系統自身。該軟體是GUI介面,但與更為著名但功能稍弱的Visual Studio Debugger幾乎完全不同。
                                                                                                  資料來源:維基百科

簡單來說,由於WinDBG可以用來調適內核,絕大多數寫Windows驅動的工程師都是用這款強大的工具來做調適程序,而我們之後由於要解說病毒及加殼的原理,也會要利用PEB來進行Kernel32.dll的記憶體空間的解析,所以熟悉操作這款工具,在我們之後的課程理解上會有相當大的幫助。

正文:

在使用WinDBG之前,我們先進行環境安裝。
我們有幾個需求:虛擬機、作業系統、WinDBG

先來講一下作業系統,對於想要研究Windows系統的研究者來說,必然就要有一個相符版本的Windows系統光碟,因為每一代的內核都會跟上一版本有著不同的差異,所以選對版本是很重要的事情。

例如你可能是要實做WindowsXP packed2的IE6溢出攻擊,那麼就可能就要掏鈔票買相符版本光碟用於虛擬機的環境安裝,才有辦法繼續進行實驗。

而最近知道了Micro$oft公佈了各版本的Windows系統VM,實在是令人興奮的消息。
讓各位知道這則消息的人,不必像我一樣為了一個實驗環境花了快六千塊買一個WindowsXPProfessional版本了。



























Google搜尋Windows vm










































找到VitualMachine-Windows Dec Center,點選進入


















選擇相符合的版本進行下載。


接著安裝WindDBG


虛擬機的安裝就不在多介紹了,不過我用的是VMWARE這款軟體,之後我會用它來進行雙機
調適。






2016年2月10日 星期三

使用Python 做出掃描後門的程序(一)

撰寫於 2016/2/11 下午
前提

這是一個後臺掃描程式,可以多線程掃描目標網址的管理者登入後台,過幾天我會再寫一篇專門一行行詳細解說 其中的doc.txt可以在我的git專案裡找到,是我蒐集得來的字典檔。

git clone  https://github.com/littletrojan/SiteScaner.git

#!python3

import os
import urllib.request
import urllib.parse
import threading
import queue
import time 
import random
from optparse import OptionParser
import sys
import progressbar
'''Here is about the optionalparser '''
usage = "usage: %prog [options] arg1 arg2"
parser=OptionParser(usage=usage)

#Thread number setting parser
parser.add_option("-t","--thread",dest="thread_num",type="int",help="Open thread number(optional)",default="1")

#Target name setting parser
parser.add_option("-u","--url",dest="url",type="string",help="Target url to scan(required)")

#Show detail message setting parser
parser.add_option("-v",dest="show_message",action="store_true",default=False,help="Set this argument to show the detail(optional)")

#define dictionary setting parser,default using doc.txt whitch content more than 40000 list of path.
parser.add_option("-d","--dict",dest="dictionary",metavar="FILE",default="doc.txt")

#define the execlution name in the dictionary want to exclude
parser.add_option("-e","--execlude",dest="exclude_list",action="append",help="Setting the excludtion extend file name whitch you don't want to try,like .jpg .gif etc")

exclude_list=['.jpg','.gif','.css','.png','.js']
user_make_thread_dead=False

class HTTPBackendScanner(object):
    
    result_list=[]
    Baidu_Spider=""
    Charset=""
    def __init__(self,local_threading_num,local_domain_name,local_showdetail,local_excludelist,local_dictionary): 
        self.threading_num=local_threading_num
        self.domain_name=local_domain_name
        self.UserAgent="Mollize6.0"
        self.Charsetr="UTF8"
        self.showdetail=local_showdetail
        self.excludelist=local_excludelist
        self.q=queue.Queue()
        self.Queue_num=0
        self.dictionary=local_dictionary
    
    '''
    Before starting the crawler we should parse the dictionary,and exclude the file we don't really want,
    and put it in to the queue in the end.
    '''
    def DictParser(self):
        print("Starting to parse dictionary line by line...")
        with open (dictionary,"r") as lines:
            for line in lines:
                line=line.rstrip()
                if os.path.splitext(line)[1] not in exclude_list:
                    self.Queue_num+=1
                    self.q.put(line)
            print("There are %s path in the list" %(self.Queue_num))
            

    def crawler(self):
        global users_make_thread_dead
        HttpStatus=''
        print("thread %s  strart "% (str(threading.get_ident())))
        while (not self.q.empty())and(user_make_thread_dead == False):
            path=self.q.get()
            url="%s%s" %(domain_name,path)
            opener=urllib.request.build_opener()
            urllib.request.install_opener(opener)
            headers={}
            headers['User-Agent']=self.Baidu_Spider
            headers['Content-Type']=self.Charset
            data=urllib.parse.urlencode(headers)
            bData=data.encode('ascii')
            request=urllib.request.Request(url,bData)

            try:
                print("Try to connecting %s"%(url),end='\t')                    #We dont want it to change line print.
                response=urllib.request.urlopen(request)
                content=response.read()
                if len(content):
                    finalurl = response.geturl()
                    if finalurl!=url:
                        if self.showdetail:
                            print("Detect redirectrion by server! We are in %s now"  %(finalurl))
                        else:
                            print("{0}".format("303 Redirection"))
                    #print(threading.Thread.getname())
                    #print("States[%s]:Path:%s" % (str(response.getcode()), url))
                    else:
                        self.result_list.append(url)
                        print("States[%s]:Path:%s" %(str(response.getcode(),url)))
            except urllib.error.HTTPError as e:
                print(e.reason)
                if e.reason.lower()!="not found":
                    raise
                '''
                if self.showdetail:
                    print ("Get error in HTTP connection",end ="")
                    print(e.getreason)
                    if self.HttpErrorHandler(e.getreason):
                        
                else:
                    if self.HttpErrorHandler(e.getreason):
                        continue
                    else:
                        sys.exit(1)
                '''
                pass
    def HttpErrorHandler(self,errstr):
        if errstr=="not found":                                                     #If http error is 404 not found
            return True
        else:
            return False
        

    
    def print_result(self):
        for list in  self.result_list:
            print(list)

    '''
    After HttpBackenScan start all work will use thread to do.
    '''
    def starting_thread(self):
        for i in range(threading_num):
            t=threading.Thread(target=self.crawler)
            t.daemon=True                                                       #Make sure when main thread exit ,the others thread will kill themself too!
            t.start()
            UserInput=input("input any word to stop!\n")
            global user_make_thread_dead
            user_make_thread_dead==True
            self.print_result()
    '''
    Scaner's main logic  function
    '''
    def run(self):
        self.starting_thread()
        self.print_result()



if __name__=="__main__":
    (option,args)=parser.parse_args()
    if (option.url==None):                              #if user pass none url.
        parser.print_help()
        exit(1)
        
    print("Program is start!")
    print(option.url)
    threading_num=option.thread_num                     #specified the thread numbers.
    domain_name=option.url+"/"                          #Modify url so that it can be strcat with another file path
    print("Going to parsing url:"+domain_name+"\n")          #print url after it has benn modify.
    userinput=input("Type any word to continue...or type quit to quit.,type help to get help")
    if userinput.lower()=="quit":
        print("byebye")
        sys.exit(0)
    elif userinput.lower()=="help":
        parser.print_help()
    else:
        pass        
    showdetail=option.show_message                      #Show the detail or not
    excludelist=exclude_list
    dictionary=option.dictionary
    scanner=HTTPBackendScanner(threading_num,domain_name,showdetail,excludelist,dictionary)
    scanner.DictParser()
    scanner.run()

加殼及脫殼(二)

撰寫於 2016/2/11 中午


了解殼的運行流程

課程的前導知識為:基礎PE結構認知

以常見的在宿主直接添加區段的殼程序為例。
首先我們先來看一下沒被加殼前的程序。

   
這是一個準備要被加殼的文件,PE頭的程式入口點指向程序的執行區段。

正如一個正常運作的執行檔。





















在準備加殼之前,加殼程序會讀取宿主程序的基本訊息,並根據這些信息與使用者的設定來對代 碼段(.text)、數據段(.data)、資源段(.rsrc)進行有選擇的加密壓縮操作。
 
 然後加殼程序會在宿主程序中,添加一個足夠大的空區段,並將負責解的代碼(術語可以稱作  為:Stub部分或Shell部分)與相關配置信息寫入這個新添加的空區段中。









而加殼後,PE文件被添加了新的區段.shell,且
原本的.text,.data,.rsrc區段都被加密,當使用靜態分析軟體反編譯該區段時,將會發現這裡是無法被解析的。

有時候也會看到被加密的節段,被加殼程序重新整合,分段成其他節塊。

另外,可以看見PE程序的入口點改變了位置
指向到新增區段.shell的入口點,也就是殼的入口位置。

也就是說,當系統執行文件並裝載程序時,他所會先執行的並不是原本該宿主的代碼,而是先執行我們新貼加在宿主上的殼程序,與所謂的計算機病毒原理相當類似。

殼的程序在被執行的這段時間,會將原本被加密的區段進行解密,當全部解密完畢後,才跳至原本宿主的OEP,正常的執行程序。






以上,就是一個基本殼的執行流程。



                                                              參考資料:黑客免殺攻防、加密與解密

加殼以及脫殼(一)

2016/2/11 撰寫於深夜

前提:
          由於最近在編寫出自己的殼,故先寫出了這篇文章。
          第一篇是科普掃盲文章,請知道基本原理並想繼續深入的人跳至第二章。


什麼是加殼?

在生活中,植物用殼保護它的種子,某些動物也同樣用殼保護自己脆弱的身體,而在計算機領域中,同樣有殼來保護軟體本身。


加密殼

如果你曾使用過破解版軟體或所謂的綠色版軟體,那些補丁就是由所謂的破解者(Cracker)、或逆向工程研究者如我(Cracker)所寫出來的。

而軟體廠商為了防止我們這些破壞他們商業利益的人成功地做出破解補丁,他們通常
會在他們所發佈的軟體上做一些手腳,增加破解者們破解的困難度,拖延他們寫出補丁時間,直到讓他們花費在破解上的精力遠遠大過於從口袋中掏出鈔票買正版軟體的花費為止。

除了商業軟體會用到所謂的加殼保護技術,不少惡意軟體的作者也會幫自己成品加殼,除了讓特徵碼掃描型防毒軟體難以辨識之外,還增加了反病毒工程師解密及理解病毒執行過程的時間。


壓縮殼?

有些人也加殼技術利用於壓縮軟體上,因為壓縮的過程本身就可以視為另外一種加密,如果將原加密的演算法改變為壓縮的演算法,就是所謂的壓縮殼,例如著名的開源UPX殼,甚至可以將加殼後的軟體壓縮至原本大小的三分之一。


虛擬機保護殼

雖然虛擬機保護殼基本屬於加密殼的一種,但由於它加密的方式與傳統的加密殼有著相當不同的差別,故而特別拿出來講一講。

虛擬機保護殼不僅僅只是對於代碼段進行了加密,還對於加密段使用了虛擬機技術,將原本的機械碼轉換成了只有虛擬機才懂得虛擬機械碼,當執行該加密段的時後才會由虛擬機進行轉譯。

是前公認最難被破解的殼,至今沒有人宣布完全破解使用這種技術保護的軟體,但由於使用虛擬機執行,執行的效率會慢上許多。

關於作者

2016/2/11 撰寫於深夜

關於我:

          我是一名淡江大學資工系三年級的學生,從高中開始就對程序開發就非常有興趣,從Python到C再到組合語言一一自學起來。

對所謂的黑客技術相當的嚮往,因此持續的不斷研究以及摸索相關的論文、以及書籍並加以實作。

在所有黑客技術當中對逆向工程最感興趣,因此在破解、漏洞分析、計算機病毒、後門實作等二進制軟體安全領域研究得最為深入。

打算在寒假結束之後在校內創立"資訊安全研究社",將我所學所知教學給相同有志為資訊安全獻心力的人,帶人跨入資訊安全領域的門檻,讓其他人少走一些遠路。

我為什麼要寫這篇部落格?

        1 .對於校內所謂的"資訊安全課程"相當不滿,主要課程內容偏重於密碼學,甚至連密碼               學都稱不上,偏重於理論而對於實務上發生的問題置之不理。

        2 .相關研究領域的書籍以及內容過少且分散,難有系統的文章講明整體的架構,因此打               算將過去所學的心得加以記錄整理,來做分享。

        3 .創立社團後,我打算拋磚引玉,第一學期先由我上台擔任社團講師,必然得我需要準               備一份排得井然有序的課綱以及教材,撰寫部落格的同時也是同時在整理我腦中的資               料,並同時把一些似懂非懂的細節釐清。

        4  .希望路過的大牛能鞭斥我的文章,讓我能知道自身學習盲點在哪,讓我進步得更快。


部落格將會探討的內容
      
          因為專題我選定了題目"計算機病毒的分析實作",因此主要內容會偏向於我研究方向的的命題。
惡意軟體的分析,調適軟體的操作,以及基於Windows系統上PE格式的介紹、Windows系統內核及使用者層交互運作原理、感染PE結構實作、加殼以及脫殼方法、殼的編程原理、Hook的原理、RootKit的介紹....等等。


我將會用C語言(WindowsAPI編程)以及Python語言當作程式碼範例解說。



為何選擇以Windows當作研究目標

           我以大部份使用者所使用的作業系統作為研究目標,而往後十年來看,個人認為Windows的市占率不太會發生明顯變動。


建議參考書籍

        WindowsAPI函數大全、琢石成器彙編語言編程、PE格式權威指南、黑客免殺攻防
   (有機會再慢慢補上...)