【算法】Gh0st配置加密算法(異或、Base64)
阿新 • • 發佈:2018-02-28
異或 urn byte break down unsigned ltib else lower
1、前言
分析木馬程序常常遇到很多配置信息被加密的情況,雖然現在都不直接分析而是通過Wireshark之類的直接讀記錄。
2017年Gh0st樣本大量新增,通過對木馬源碼的分析還發現有利用Gh0st加密方式來傳播的源碼中的後門。
2、加密思路
控制端:對字符串異或、移位、Base64編碼
服務端:對字符串Base64解碼、移位、異或
3、實踐代碼
- 加密編碼
// Base64編碼 static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int C模仿Gh0st加密上線地址Dlg::base64_encode(const void *data, int size, char **str) { char *s, *p; int i; int c; const unsigned char *q; p = s = (char*)malloc(size * 4 / 3 + 4); if (p == NULL) return -1; q = (const unsigned char*)data; i = 0; for (i = 0; i < size;) { c = q[i++]; c *= 256; if (i < size) c += q[i]; i++; c *= 256; if (i < size) c += q[i]; i++; p[0] = base64[(c & 0x00fc0000) >> 18]; //base64 p[1] = base64[(c & 0x0003f000) >> 12]; p[2] = base64[(c & 0x00000fc0) >> 6]; p[3] = base64[(c & 0x0000003f) >> 0]; if (i > size) p[3] = ‘=‘; if (i > size + 1) p[2] = ‘=‘; p += 4; } *p = 0; *str = s; return strlen(s); } // 加密函數 char * C模仿Gh0st加密上線地址Dlg::MyEncode(char *str) { int i, len; char *s, *data; // 字符串長度 len = strlen(str) + 1; // 開辟字符串相對應的內存空間 s = (char *)malloc(len); // 將字符串拷貝到開辟出來的指針中 memcpy(s, str, len); // 異或操作 for (i = 0; i < len; i++) { s[i] ^= 0x19; s[i] += 0x86; } // Base64編碼 base64_encode(s, len, &data); free(s); return data; }
- 解密編碼
// Base64密鑰 static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // 解碼密鑰 int C模仿Gh0st加密上線地址Dlg::pos(char c) { char *p; for (p = base64; *p; p++) if (*p == c) return p - base64; return -1; } // Base64解碼 int C模仿Gh0st加密上線地址Dlg::base64_decode(const char *str, char **data) { const char *s, *p; unsigned char *q; int c; int x; int done = 0; int len; s = (const char *)malloc(strlen(str)); q = (unsigned char *)s; for (p = str; *p && !done; p += 4) { x = pos(p[0]); if (x >= 0) c = x; else { done = 3; break; } c *= 64; x = pos(p[1]); if (x >= 0) c += x; else return -1; c *= 64; if (p[2] == ‘=‘) done++; else { x = pos(p[2]); if (x >= 0) c += x; else return -1; } c *= 64; if (p[3] == ‘=‘) done++; else { if (done) return -1; x = pos(p[3]); if (x >= 0) c += x; else return -1; } if (done < 3) *q++ = (c & 0x00ff0000) >> 16; if (done < 2) *q++ = (c & 0x0000ff00) >> 8; if (done < 1) *q++ = (c & 0x000000ff) >> 0; } len = q - (unsigned char*)(s); *data = (char*)realloc((void *)s, len); return len; } // 解密函數 char* C模仿Gh0st加密上線地址Dlg::MyDecode(char *str) { int i, len; char *data = NULL; len = base64_decode(str, &data); for (i = 0; i < len; i++) { data[i] -= 0x86; data[i] ^= 0x19; } return data; }
然後就是加密解密界面的內容。
函數代碼:
- 生成配置信息按鈕
void C模仿Gh0st加密上線地址Dlg::OnBnBuild() { // TODO: 在此添加控件通知處理程序代碼 UpdateData(TRUE); m_remote_host.Replace(L" ", L""); m_remote_port.Replace(L" ", L""); CString str = m_remote_host + ":" + m_remote_port; str.MakeLower(); TCHAR * pWStrKey; // 合並後的內容 // 開辟數組 pWStrKey = new TCHAR[str.GetLength() + 1]; pWStrKey = str.GetBuffer(0); // 第一次 調用確認轉換後單字節字符串的長度,用於開辟空間 int pSize = WideCharToMultiByte(CP_OEMCP, 0, pWStrKey, wcslen(pWStrKey), NULL, 0, NULL, NULL); // 單字符 char* pCStrKey = new char[pSize + 1]; // 第二次 調用將雙字節字符串轉換成單字節字符串 WideCharToMultiByte(CP_OEMCP, 0, pWStrKey, wcslen(pWStrKey), pCStrKey, pSize, NULL, NULL); pCStrKey[pSize] = ‘\0‘; // 接收char* m_encode = MyEncode(pCStrKey); m_encode.Insert(0, L"AAAA"); m_encode += "AAAA"; UpdateData(FALSE); }
- 解密配置信息按鈕
void C模仿Gh0st加密上線地址Dlg::OnBnGetLoginInfo()
{
// TODO: 在此添加控件通知處理程序代碼
UpdateData(TRUE);
// 1 獲取加密編輯控件裏的字符串
int pSize = m_encode.GetLength() + 1;
wchar_t * pStart, *pEnd;
wchar_t strKey[] = L"AAAA";
wchar_t strEncode[1024];
// 拿到最開始的字符串,如果前面是AAAA就賦值到pStart
pStart = wcsstr(m_encode.GetBuffer(0), strKey);
// 前移動4個字節,也就是跳過AAAA
pStart += 4;
// 如果AAAA匹配不到把strKey,也就是AAAA賦值給pEnd
pEnd = wcsstr(pStart, strKey);
// 清空原先AAAA字符串
wmemset(strEncode, 0, wcslen(pStart) + 1);
// 取key值之間的內容,配置字符串 - 字符串長度,取前面的真實加密字符串
wmemcpy(strEncode, pStart, pEnd - pStart);
// 單字符
char* pCStrKey = new char[wcslen(strEncode) + 1];
// 調用將雙字節字符串轉換成單字節字符串
WideCharToMultiByte(CP_OEMCP, 0, strEncode, wcslen(strEncode) + 1, pCStrKey, wcslen(strEncode) + 1, NULL, NULL);
pCStrKey[pSize] = ‘\0‘;
// 解密代碼
m_decode = MyDecode(pCStrKey);
UpdateData(FALSE);
}
4、實際效果
5、參考
gh0st3.6源碼分析(1)——木馬的生成
http://blog.csdn.net/hjxyshell/article/details/19094609
【算法】Gh0st配置加密算法(異或、Base64)