做CTF題好長一段時間了,真的可以學到很多東西。這次,我們開啟 net-force.nl 的 Steganography之旅,所謂的隱寫術。
level 801: Training - Can you see me?
點開上面的鏈接可以查看題目。字的顏色以背景顏色書寫,慣用的雕蟲小技,Ctrl + A 就能現形,或者查看網頁代碼,答案顯而易見。
<span style="color: white">Look at the file passWord.gif and you will find the password for the next challenge page easy!!!...You hope ;-)</span>
可是文件 password.gif 在哪里?搜索了網頁代碼,沒找到引用的地方,嘗試在該級目錄下追加名字 password.gif 打開
咦,圖片壞掉了?圖片存到本地,或者直接用 wget 命令拉取下來查看一下。
martin@M2037:~/ctf/net-force.nl$ wget https://net-force.nl/challenge/level801/password.gif
--2015-10-25 23:14:29-- https://net-force.nl/challenge/level801/password.gif
Resolving net-force.nl (net-force.nl)... 83.137.145.137
Connecting to net-force.nl (net-force.nl)|83.137.145.137|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 56 [image/gif]
Saving to: ‘password.gif’
100%[=======================================================>] 56 --.-K/s in 0s
2015-10-25 23:14:31 (196 KB/s) - ‘password.gif’ saved [56/56]
martin@M2037:~/ctf/net-force.nl$ file password.gif
password.gif: ASCII text, with CRLF line terminators
martin@M2037:~/crack/net-force.nl$ vim password.gif
martin@M2037:~/ctf/net-force.nl$ cat password.gif
hehe...nope it's just a text file :)
password = stegano
被欺騙了,原來它就不是什么圖片,是ASCII文本。這讓我想起了聲聲嘆的第七則笑話,關于PNG改后綴。
然而,這場戰役才剛剛開始。隱寫就是將秘密藏在公共信息里,讓你察覺不出來,達到傳輸出去的目的;而加密會明確告訴你密文(一般也會有加密方法),讓你推算明文消息。三十六計中的第一計瞞天過海:備周則意怠,常見則不疑。陰在陽之內,不在陽之對。太陽,太陰。如果之前沒讀過,可以抽時間好好讀一下了。兵法上說秘計往往隱藏于公開的事物里,而不在公開事物的對立面上,隱寫術也是這么玩的,給你"明修棧道"的信息,實際則"暗度陳倉"。
level 802: Go Holland Go!
There is password hidden on this page, find it...that's all (dutch word)
乍一看,又是0/1二進制字符,又是紅黑藍三種顏色的,玩什么把戲?
遠遠地看,這字母大片的0大片的1,中空的數字0構成四個字母TULP,難道這就是答案了?輸入回車,果然是,那這也太簡單了。
是否感覺題目不過如此?難度級別在慢慢增大,更有挑戰性的還在后面。
如果你對這樣的書寫感興趣,可以搜索關鍵字"圖片轉ASCII",算法大致的思路是,顏色抖動(dither)。
如果僅用黑白兩種顏色來表達一張灰度圖/彩色圖這樣有多種顏色的圖片呢?0/1只能表達兩種顏色,可是如果每兩個像素一看,就有2*2=4種色彩了,每四個一看4*4=16種色彩了,雖然僅僅是灰度值。用字符充當灰度信息也是一個道理,一個字在一個方塊里也是兩種色,線條多的字比線條少的字看起來更"濃"一些,所以ASCII里可以用@#表示濃,,.表示淡。延伸閱讀,有關最終幻想1里面的像素的藝術: http://www.petesqbsite.com/sections/tutorials/tuts/tsugumo/chapter6.htm
level 803: Words, words, words...
Well, this is as easy as it can be... just read the password and fill it in on the challenge page!
The tiny thing, the password, sure it is that what you seek?
You need it fast? Need is one thing, for what you need the password anyway?
The challenge? Look at this page, if the password is what you want.
Again I say, Look!
雖然指明了說密碼就在文字里,可一個一個地試答案,就沒多大意思了,我們需要知道背后的邏輯。
我在做caesum.com 的題目 Unix finger is not aching 搜索到 http://www.phearless.org/istorija/razno/bsteg.txt ,也許對你以后做類似的題有啟發。
文本隱寫可以在每個單詞的字母位置,每個段落的字母位置和每個段落的單詞位置做文章。
很多人玩過文字游戲藏頭詩,將要表達的話用每句話的地一個字串起來。例如,幫忙用"武婷婷我愛你",做成藏頭詩來表白。
武大郎!
停下!
停下!
我要買燒餅!
愛!好咧!
你要幾個!
笑夠了,該做題了。段落的最后一句Again I say,是不是像在說"都說了是Again了"?
The tiny thing, the password, sure it is that what you seek?
You need it fast? Need is one thing, for what you need the password anyway?
The challenge? Look at this page, if the password is what you want.
Again I say, Look!
每隔三個單詞一摘?。篢he password that You Need for the challenge page is Again.
不知道答案是否講究大小寫,一試便知。
Level 804: “Nice colors eh?”
Uhm ok, get the password out of this image...it's a dutch word :)
很單調的圖像,只有幾種顏色,把顏色數值提取出來。
Color 1: 8B8B61 Color 2: 8B8B61 Color 3: 8B8B70
Color 4: 8B8B6A Color 5: 8B8B65 Color 6: 8B8B73
將字符連在一起顯示,很容易被發現,于是有了上面的,只采用單一的通道書寫,稍微提高了隱蔽性。
前面的都是8B8B,我們把后面的藍色通道信息提取出來 61 61 70 6A 65 73,粗看,他們就在小寫字母(a-z, 0x61-0x7a)的范圍內。
PRintf "/x61/x61/x70/x6A/x65/x73/n"
Level 805: Another picture!
Another dutch word is hidden in this image ;)
給了一張木偶(puppet)的圖片,文件名 monster.jpg
關于圖片的隱寫,第一步就是像上一題一樣,查看是否隱藏的信息被當成像素,或者圖片元信息寫入了圖片。
這個時候,strings 命令就是你的朋友了。
martin@M2037:~/ctf/net-force.nl$ strings monster.jpg
JFIF
$.' ",#
(7),01444
'9=82<.342
!22222222222222222222222222222222222222222222222222
...
mNYe%L
j^'6
wvT
@!Fx
)01101011011011110110010101101011011010100011001101110011.
開頭的一串2倒是沒什么,末尾的0/1字符串行跡特別可疑,為什么呢?首先它看起來就像??!
martin@M2037:~/ctf/net-force.nl$ echo -n "01101011011011110110010101101011011010100011001101110011" | wc
0 1 56
martin@M2037:~/ctf/net-force.nl$ echo "01101011011011110110010101101011011010100011001101110011" | sed -r "s/([01]{8})//1 /g"
01101011 01101111 01100101 01101011 01101010 00110011 01110011
用wc一下,長度是56,剛好可以湊成7個字符,用 sed 再分割一下解析文本成ASCII字符,也可以用Python的struct模塊,方便!
我之前的文章C++ 的二進制語法與語義第二種方法也給出了如何解析。
level 806: Just a flag...
There's a password inside this icon...
martin@M2037:~/ctf/net-force.nl$ file flag.ico
flag.ico: MS Windows icon resource - 2 icons, 32x32, 16 colors
martin@M2037:~/ctf/net-force.nl$ strings flag.ico
V.qK
file.txt
wgyM
V.qK
file.txtPK
看到了PK,條件反射地想到這個文件可能會有.zip文件,file.txtPK,可以提取出file.txt。
用dd命令,或者Notepad++/wxHexEditor/010 Editor之類的二進制編輯工具提取出來。
提取過程可以參考之前的題解--題目2 Stegano Attachment
0000430: 0000 ffff 0000 504b 0304 0a00 0900 0000 ......PK........
0000440: a784 562e 714b c313 2400 0000 1800 0000 ..V.qK..$.......
0000450: 0800 0000 6669 6c65 2e74 7874 a5c8 d381 ....file.txt....
0000460: cc63 5ab4 1cd1 d623 9677 6779 4dbb 5856 .cZ....#.wgyM.XV
0000470: 03bd 7d63 c3cf 4ee3 dd1f 917c 1662 e6b1 ..}c..N....|.b..
0000480: 504b 0708 714b c313 2400 0000 1800 0000 PK..qK..$.......
0000490: 504b 0102 1400 0a00 0900 0000 a784 562e PK............V.
00004a0: 714b c313 2400 0000 1800 0000 0800 0000 qK..$...........
00004b0: 0000 0000 0100 2000 8081 0000 0000 6669 ...... .......fi
00004c0: 6c65 2e74 7874 504b 0506 0000 0000 0100 le.txtPK........
00004d0: 0100 3600 0000 5a00 0000 0000 ..6...Z.....
martin@M2037:~/ctf/net-force.nl$ dd if=flag.ico of=file.zip skip=`printf "%d" 0x0000436`
dd: ‘flag.ico’: cannot skip to specified offset
0+0 records in
0+0 records out
0 bytes (0 B) copied, 0.00348879 s, 0.0 kB/s
martin@M2037:~/ctf/net-force.nl$ dd if=flag.ico of=file.zip skip=`printf "%d" 0x0000436` bs=1
166+0 records in
166+0 records out
166 bytes (166 B) copied, 0.0110782 s, 15.0 kB/s
martin@M2037:~/crack/net-force.nl$ file file.zip
file.zip: Zip archive data, at least v1.0 to extract
martin@M2037:~/ctf/net-force.nl$ unzip file.txt
Archive: file.txt
[file.txt] file.txt password:
解壓的時候,提示要輸入密碼,只能暴力破解了。不過這樣的題一般意思到就行了,不會出很復雜的密碼。
推薦.zip格式密碼破解工具fcrackzip
先benchmark一下,也就是Android手機界里常說的跑分,看哪種方法在本機上快就選哪個來破解。
martin@M2037:~/ctf/net-force.nl$ apt-cache search fcrackzip
fcrackzip - password cracker for zip archives
martin@M2037:~/ctf/net-force.nl$ sudo apt-get install fcrackzip
[sudo] password for martin:
Reading package lists... Done
Building dependency tree
Reading state information... Done
fcrackzip is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 324 not upgraded.
martin@M2037:~/ctf/net-force.nl$ fcrackzip --benchmark
cpmask: (skipped)
zip1: cracks/s = 0451414
*zip2, USE_MULT_TAB: cracks/s = 0442891
martin@M2037:~/crack/net-force.nl$ fcrackzip file.zip -u -v -m zip2 -l1 -c a
found file 'file.txt', (size cp/uc 36/ 24, flags 9, chk 84a7)
PASSWORD FOUND!!!!: pw == a
原來它用了最簡單的字符a作密碼,fcrackzip參數的意思man一下
-u, --use-unzip: 嘗試解壓文件,防止誤判(false positive)
-v, --verbose: 輸出更多信息
-m, --method name: 用的破解方法,我的機器默認的是zip2,所以可以不寫。
-l, --length min[-max]: 密碼長度,由短至長慢慢破解,奈何一下就發現。
-c, --charset characterset-specification 搜索空間,也就是字符集。a表示在小寫字母里搜索。
a include all lowercase characters [a-z]
A include all uppercase characters [A-Z]
1 include the digits [0-9]
! include [!:$%&/()=?{[]}+*~#]
: the following characters upto the end of the specification string are
included in the character set. This way you can include any character
except binary null (at least under unix).
例如,aaaa可以匹配單詞flag。a1:$% 表示在小寫字母,數字,美元符號和百分號之間搜索。
-p, --init-password string: 初始值,從某個密碼開始搜索,或者用字典密碼,暫未排上用場。
martin@M2037:~/crack/net-force.nl$ unzip file.zip
Archive: file.zip
[file.zip] file.txt password:
replace file.txt? [y]es, [n]o, [A]ll, [N]one, [r]ename: y
extracting: file.txt
martin@M2037:~/crack/net-force.nl$ cat file.txt
The password is: *******
為了防止泄漏密碼,我還是打上馬賽克,哈哈~
注意,標點符號可能也是密碼的一部分。
level 807: Learn See Become
Get the password from the text below!
Text:
2C7CBi*66iC6C2BBB3i6B36i<;][XJ/D>AQJ>Q7[/C;|Q[M]>917,.E.|G]B>S.2X3YXYXXY./YY.2Y3XY32.X.Yl//lmml.63mm2*l6.+7lml622336*26/
注意到這一題目與其他題目的不同,題目三個連續的動詞,從語法上講是有錯誤的,它想說明什么?要學會看,學會觀察和分析。
首字母均大寫,合起來是LSB,想到了什么?在程序中處理過大小端的朋友一定會想到MSB/LSB縮寫。
難道他是在提醒Least Significant Bit么?嘗試先把這些位提取出來,你如果熟悉C語言,就用C語言拽出來吧。
martin@M2037:~/ctf/net-force.nl$ echo -n '2C7CBi*66iC6C2BBB3i6B36i<;][XJ/D>AQJ>Q7[/C;|Q[M]>917,.E.|G]B>S.2X3YXYXXY./YY.2Y3XYl.63mm2*l6.+7lml622336*26/' | xxd -b -c 1 | awk '{print $2}' | sed -r 's/[01]{7}([01])//1/g' | tr -d -c '01'
011101000110100001100101011100000110011101101111011100100110010001101001011100110110000101101100011100000110100001100001
xxd -b 表示工作在二進制模式
tr -d -c '01' 過濾掉不是 0/1 的字符
sed -r 's/([01]{8})//1 /g' 意思是每8個用空格分割一下
sed -r 's/([01]{8})//1 /g'
01110100 01101000 01100101 01110000 01100111 01101111 01110010 01100100 01101001 01110011 01100001 01101100 01110000 01101000 01100001
然后就是二進制解析了,怎么熟悉就怎么來吧。
#include <stdio.h>#include <string.h>#include <stdlib.h>int main(){ // http://en.cppreference.com/w/cpp/language/string_literal // const char raw[] = R"###(2C7CBi*66iC6C2BBB3i6B36i<;][XJ/D>AQJ>Q7[/C;|Q[M]>917,.E.|G]B>S.2X3YXYXXY./YY.2Y3XY32.X.Yl//lmml.63mm2*l6.+7lml622336*26/)###"; // or you have to escape charactors like " / (diliberately put / at the end) const char raw[] = "2C7CBi*66iC6C2BBB3i6B36i<;][XJ//D>AQJ>Q7[//C;|Q[M]>917,.E.|G]B>S.2X3YXYXXY./YY.2Y3XY32.X.Yl//lmml.63mm2*l6.+7lml622336*26/"; const char binary[] = "01110100 01101000 01100101 01110000 01100111 01101111 01110010 01100100 01101001 01110011 01100001 01101100 01110000 01101000 01100001"; printf("length: %zu/n", strlen(raw)); const char* begin; char* end = const_cast<char*>(binary); do { begin = end; long int byte = strtol(begin, &end, 2/*base*/); putchar(static_cast<int>(byte)); } while(begin != end); putchar('/n'); return 0;}
output:
length: 120
thepgordisalpha
the pgord is alpha
net-force.nl中的nl是荷蘭(Netherlands)的字符編碼縮寫,
pgord 是什么玩意兒,荷蘭語單詞"密碼"?維基字典查了下,好像不是。百度一下有驚喜。
level808: How good are your eyes?
stip是什么意思?好像不是什么單詞.只能找到 stipple,可能就是這個了。
stipple 點畫,點描;點刻(指雕刻)
檢查了下,圖沒有什么不正常的。
用專業修圖工具GIMP打開查看,粗看沒什么,放大幾倍查看,有好幾個紅點。位置不規則,連起來也看不出什么,定位一下坐標再看。
martin@M2037:~/ctf/net-force.nl$ gimp stip.bmp
記下紅點的坐標和像素值
(100, 0): 1946FA
( 34, 1): 3246FA
(130, 15): 2D46FA
( 20, 17): 2846FA
( 90, 21): 1E46FA
(100, 21): 1446FA
(150, 39): 0F46FA
(180, 59): 2346FA
(171, 100): 0A46FA
像素綠藍通道都是一樣的46FA,紅色通道不是字母或數字對應的ASCII字符,好像有什么其他的規律?提取出來單獨看。
19 32 2D 28 1E 14 0F 23 0A
0A 0F 14 19 1E 23 28 2D 32 從小到大排列是等差數列,說明什么呢?
坐標值倒是可打印的字母,難道把密文藏在坐標里了?試著把前面的坐標值也排列一下。
GoOdEy/03s!
好像是答案了,不過有一個字符的值是3,根據本題的題目先猜 GoOdEyes!
leet speak 里3和e是一樣的,不過這里是數字3,不是ASCII字符3(51)
那就用3再試試,GoOdEy3s!嗯,我眼神還是很好的嘛~
level809: Did you try it 100x?
看到歪歪斜斜的條,我馬上意識到圖片的尺寸可能有問題。
因為大學做過數字圖像處理,BMP文件的讀寫需要四字節對齊,如果沒有的話,會出現這樣的鋸齒效果。
對BMP文件格式作一番了解后,結構體(struct)需要采用一字節對齊(32位機器默認是四)才能讀寫正確。
010 editor 是很不錯的二進制編輯軟件,強烈推薦,因為有很多模板可以使用。Templates > BMP template
對圖片的每個字節意思都給予解釋,不明白的會轉換不同類型顯示。
圖中尺寸47x50,但是字節數有sizeImage=30000,BitCount是24位,每個像素是RGB形式,占3個字節。
w*h的結果應該是10000,開方一下width=height=100,看到結果 o3ps
如果你改成 width=200,height=50,你會看到左右兩個 o3ps,神奇嗎?改了兩個像素就出現這種效果。
圖像其實就是二位數組,這就是MATLAB里對二維矩陣 reshape 后的效果。
其實還有很多可以在圖片文件上作文章的stegano想法。
level811: Ancient Voices
Your task speaks for itself, find the hidden password.
The program 'pngcheck' is currently not installed. You can install it by typing:
sudo apt-get install pngcheck
$ pngcheck giza.png
giza.png illegal (unless recently approved) unknown, public chunk cHRm
ERROR: giza.png
PNG 的 chunk 都是四個字符組成的32位int,我記得好像一般首字母小寫,后面三個字母大寫。
還是上代碼吧,摘取 /usr/include/png.h
#define PNG_INFO_gAMA 0x0001#define PNG_INFO_sBIT 0x0002#define PNG_INFO_cHRM 0x0004#define PNG_INFO_PLTE 0x0008#define PNG_INFO_tRNS 0x0010#define PNG_INFO_bKGD 0x0020#define PNG_INFO_hIST 0x0040#define PNG_INFO_pHYs 0x0080#define PNG_INFO_oFFs 0x0100#define PNG_INFO_tIME 0x0200#define PNG_INFO_pCAL 0x0400#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */#define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */
cHRm chunck 有問題,是筆誤還是故意寫錯的呢?
chromaticity是色度的意思,the quality of a color as determined by its dominant wavelength
name value start size color
struct CHUNK chunk[13] cHRm (Ancillary, Public, Safe to Copy) 196h 313Fh Fg: Bg:
uint32 length 12595 196h 4h Fg: Bg:
union CTYPE type cHRm 19Ah 4h Fg: Bg:
ubyte data[12595] 19Eh 3133h Fg: Bg:
uint32 crc D97638D7h 32D1h 4h Fg: Bg:
martin@M2037:~/ctf/net-force.nl$ dd if=giza.png of=giza.cHRm ibs=1 skip=0x19E count=0x3133
dd: invalid number ‘0x19E’
martin@M2037:~/ctf/net-force.nl$ dd if=giza.png of=giza.cHRm ibs=1 skip=`printf "%d" 0x19E` count=`printf "%d" 0x3133`
12595+0 records in
24+1 records out
12595 bytes (13 kB) copied, 0.0244755 s, 515 kB/s
$ file giza.cHRm
giza.cHRm: ISO Media, MPEG v4 system, version 1
$ vlc giza.cHRm
用音樂播放器播放,音節大概聽出來是tu tan ga mang搜索一下,中文提示"圖坦卡蒙"。
題目中給的圖片是金字塔,所以大概就是指這個人了。
圖坦卡蒙(前1341-前1323年)是古埃及新王國時期第十八王朝的法老。
Tutankhamun
應該就是這個人了,與埃及金字塔有關,順便了解了一下這個埃及法老。
圖坦卡蒙的詛咒:誰擾亂了這位法老的安寧,‘死神之翼’將在他頭上降臨。
數十年來,凡是膽敢進入法老墓穴的,幾乎一一應了咒語,不是當場斃命,就是不久后染上奇怪的病癥而痛苦地死去。
不過怎么輸入密碼都不對,去論壇看了一下。https://net-force.nl/forum/list_messages/363/Stegano_Ancient_Voices/1/
For everybody who practically solved it but fights with the spelling: the solution is all lowercase without '-' or ' ' and the spelling follows a very well known english online encyclopaedia.
@admins: If you think that this gives to much away, remove this post. But having to guess around with the spelling is just stupid.
原來不是我一個人在戰斗,很多人都遇到過這個問題。
level812: SPECtacular
I watched the river one day. It scrolled past in its colors, making a beautiful sound.
- Ivan the Zen Master
wget https://net-force.nl/challenge/level812/nfchallenge_818.mp3
用Audacity軟件打開,調到音量或者amplify一下可以聽到兩種聲音混在一起。
SPECtacular 是一個單詞,意思"場面壯觀的,引人注意的,驚動一時的"
但是前半部分大寫,后半部分小寫,是想說明由兩部分組成?
這是個有關聲音隱寫的題目,看能不能從 spectrum(光譜; 波譜; 范圍; 系列)得到提示。
如果你沒有音頻相關的職業,或者英語不是很好,可能就想不到 spectrum 了。
新聞熱點
疑難解答