2022 Pwnhub冬季赛 WP

2022 Pwnhub冬季赛

笔者以星盟安全团队队员的身份参与了本次比赛,在队内师傅们的共同努力下,最终取得了较为理想的成绩。

赛中,笔者AK了密码,非预期出了两道AI题,以及半道Airdrop取证相关的MISC题,这里便仅对以上题目进行记录、分享。

排名

rank 3
rank 3

Crypto

ASR

题目
from gmpy2 import *
from Crypto.Util.number import *
from secret import flag
m = bytes_to_long(flag)

R = getPrime(256)
S = getPrime(512)
A = getPrime(1024)

N = R * S * A
c = pow(m, 0x10001, N)

RA = R & A
print('RSA1',hex(RA * S))
print('RSA2',hex(RA | S))

print('c', hex(c))
print('N',hex(N))

# RSA1 0x97be543979cb98c109103fa118c1c930ff13a6b2562166417021afd6e46cb0837a5cc5f4094fcea5fcc33efdfa495050e0fb8269922b3ee2d403210ed1ba339af2dc3d4e8952f0c784fcc655436cf255b98cdaf8080df47f6c28bc0bae68c713
# RSA2 0xa887aa84f3a0bd8b79ed59a7bb98d8e58a85414f85cf2ddf53ff4bd9294bfdadf7d6d6adfe7fbed55fc71b5a6bfcfe79ced27e2f41e7546a8679daf5b63dda37
# c 0x2f62fb7e7e8e27823193119f8412050ade9084ade25261a5875da23a07d5d5145e72d460697984d8aa668a25822009a4fdc85df2b208941cd3219b312f21c3c7bc4ef7aa8c18b4f91a0e815fe1892fca0f72406e571fbd0fea2c4710c601165ccd7e8a5a828721a5e2c956b732223d683d1413ef393b5f80a431c52bf9099e22b8e27daafb9d3e055242b89b5419b8925744ccf348e1bea519225af8efe7dbcc202425251039cbfe6b892a7fcf7e9d72224ea9381e3fb32ab837139af4b4112a3c7a6571c88e7d6c5db4c3f91e25edd15eb5544ef2f29a9e1bb1062ec86f1902
# N 0x58a7ff25292651e1a8d82656d64fe3b458d6e688405e85aa6c02e0c33469ad3dbaef6c6eaf8faf22f2d15e80856ab7b90a40fd50c36f7b59932bc94e6fb4fabefa87b11bf4ef74df4ccf8d254f0c6812628df3c5b3786af35e3dde9c87b462d1a565af6f100750718ccb7235174947f00cec5836765150f1680d0c58a5f9ea2473a6033c218c75664dc53377dde9386f37e1a89d77e61a716129d290c5a41f81cd3490bab6fe51f232ab27cb1ac9c8eb88e908c12109a125b7439c25b6879283a17a3467823fbb089709eb836cfd03386cc4bf186eb45401472ab0bdec605fd7
题解

R S A 1 = R A ∗ S RSA1=RA * S RSA1=RAS N = R ∗ S ∗ A N = R * S * A N=RSA, 易知: S = g c d ( R S A 1 , N ) S = gcd(RSA1, N) S=gcd(RSA1,N)

由题目可知,S是512位的大数,一般flag转数字后是没512位那么大的。再根据同余式性质,可以直接把N的因子S当作新的模数n

而素数S的欧拉函数有: p h i = S − 1 phi = S-1 phi=S1. 再下来,就是最基本的RSA解密了.

至于为什么能篡改N,这里给出证明如下:
n = p ∗ q c = m e m o d    n c + k • p • q = m e c = m e m o d    p \begin{aligned} n &= p*q \\ c &= m^e \mod n \\ c +k•p•q &= m^e \\ c &= m^e \mod p \end{aligned} ncc+kpqc=pq=memodn=me=memodp
再推广下,无论n有多少因子构成,只要求出n的任何一个因子其实都可以拿来当新的n来用

但若要正确求出明文,就还得满足这个因子大于m

import gmpy2
import libnum

RSA1 = 0x97be543979cb98c109103fa118c1c930ff13a6b2562166417021afd6e46cb0837a5cc5f4094fcea5fcc33efdfa495050e0fb8269922b3ee2d403210ed1ba339af2dc3d4e8952f0c784fcc655436cf255b98cdaf8080df47f6c28bc0bae68c713
c = 0x2f62fb7e7e8e27823193119f8412050ade9084ade25261a5875da23a07d5d5145e72d460697984d8aa668a25822009a4fdc85df2b208941cd3219b312f21c3c7bc4ef7aa8c18b4f91a0e815fe1892fca0f72406e571fbd0fea2c4710c601165ccd7e8a5a828721a5e2c956b732223d683d1413ef393b5f80a431c52bf9099e22b8e27daafb9d3e055242b89b5419b8925744ccf348e1bea519225af8efe7dbcc202425251039cbfe6b892a7fcf7e9d72224ea9381e3fb32ab837139af4b4112a3c7a6571c88e7d6c5db4c3f91e25edd15eb5544ef2f29a9e1bb1062ec86f1902
N = 0x58a7ff25292651e1a8d82656d64fe3b458d6e688405e85aa6c02e0c33469ad3dbaef6c6eaf8faf22f2d15e80856ab7b90a40fd50c36f7b59932bc94e6fb4fabefa87b11bf4ef74df4ccf8d254f0c6812628df3c5b3786af35e3dde9c87b462d1a565af6f100750718ccb7235174947f00cec5836765150f1680d0c58a5f9ea2473a6033c218c75664dc53377dde9386f37e1a89d77e61a716129d290c5a41f81cd3490bab6fe51f232ab27cb1ac9c8eb88e908c12109a125b7439c25b6879283a17a3467823fbb089709eb836cfd03386cc4bf186eb45401472ab0bdec605fd7
e = 65537
S = int(gmpy2.gcd(RSA1, N))
phi = S-1
d = int(gmpy2.invert(e, phi))
m = int(pow(c,d,S))
print(libnum.n2s(m))
# flag{b66f68258f184bd7afddd32c1518eed0}

大杂烩

题目
# sage
from Crypto.Util.number import *
from gmpy2 import *
from random import *

padding = lambda num, bit_len: (num << (512 - bit_len)) + getrandbits(512 - bit_len)

flag = b'**************************************'
m1, m2 = bytes_to_long(flag[:19]), bytes_to_long(flag[19:])
p = next_prime(padding(m1, m1.bit_length()))
q = next_prime(padding(m2, m2.bit_length()))
n = p * q
e = getPrime(128)
d = inverse(e, (p - 1) * (q-1))
a, b = e & 0x3ffffffffff, e >> 42
N = getPrime(128)
E = EllipticCurve(Zmod(N), [a, b])
NN = getPrime(1024)
S = inverse(getPrime(128), NN) * inverse(getPrime(128), NN)
d1 = d >> 512
d2 = d & (1 << 512) - 1
enc1 = S * d1 % NN
enc2 = S * d2 % NN

print('n =', n)
print('a =', a)
print('N =', N)
print('POINT =', E.lift_x(996))
print('enc1 =', enc1)
print('enc2 =', enc2)
print('NN =', NN)


# n = 117749279680045360245987277946945707343578937283621512842997606104123872211782263906911929773756533011817679794905642225389185861207256322349591633257348367854563703050789889773031032949742664695416275919382068347995088593380486820784360816053546651916291080971628354468517506190756456913824397593128781030749
# a = 1755716071599
# N = 236038564943567983056828121309828109017
# POINT = (996 : 151729833458737979764886336489671975339 : 1)
# enc1 = 98662590652068949920571979585725979127266112216583776160769090971169664292493813021843624362593669574513220457664819153878956311077379392531742253343961645534972639309537402874636739745717765969720117162780620981639015788423324884640935466801234207019510919768602974162878323777374364290185048275714332671356
# enc2 = 58738699705013897273174837829098879580829898980458718341881900446701910685043213698485036350888862454440118347362218485065377354137391792039111639199258042591959084091242821874819864955504791788260187064338245516327147327866373690756260239728218244294166383516151782123688633986853602732137707507845681977204
# NN = 149794788177729409820185150543033616327574456754306207341321223589733698623477041345453230785413920341465642754285280273761269552897080096162195035057667200692677841848045965505750839903359478511509753781737513122660495056746669041957643882516287304836822410136985711091802722010788615177574143908444311475347
题解
  1. 解方程求b,恢复出e
  2. 构造格求出d1、d2,恢复出d
  3. 已知e、d分解n,得到p、q
  4. 由p、q恢复出flag
# Sage
import gmpy2, libnum
import random

a = 1755716071599
N = 236038564943567983056828121309828109017
x,y = 996,151729833458737979764886336489671975339
PR.<b> = PolynomialRing(Zmod(N))

# y^2 = x^3 + a*x + b
f = x^3+a*x+b-y^2
b = int(f.roots()[0][0])
e = (b<<42)+a



enc1 = 98662590652068949920571979585725979127266112216583776160769090971169664292493813021843624362593669574513220457664819153878956311077379392531742253343961645534972639309537402874636739745717765969720117162780620981639015788423324884640935466801234207019510919768602974162878323777374364290185048275714332671356
enc2 = 58738699705013897273174837829098879580829898980458718341881900446701910685043213698485036350888862454440118347362218485065377354137391792039111639199258042591959084091242821874819864955504791788260187064338245516327147327866373690756260239728218244294166383516151782123688633986853602732137707507845681977204
NN = 149794788177729409820185150543033616327574456754306207341321223589733698623477041345453230785413920341465642754285280273761269552897080096162195035057667200692677841848045965505750839903359478511509753781737513122660495056746669041957643882516287304836822410136985711091802722010788615177574143908444311475347

A, d1 = matrix(ZZ,[[1, enc1], [0, NN]]).LLL()[0]
A, d2 = matrix(ZZ,[[1, enc2], [0, NN]]).LLL()[0]
d1 = abs(d1)
d2 = abs(d2)
d2 = int(str(bin(d2)[2:]).zfill(512), 2)
d = (d1<<512)+d2


n = 117749279680045360245987277946945707343578937283621512842997606104123872211782263906911929773756533011817679794905642225389185861207256322349591633257348367854563703050789889773031032949742664695416275919382068347995088593380486820784360816053546651916291080971628354468517506190756456913824397593128781030749

def divide_pq(e, d, n):
    k = e*d - 1
    while True:
        g = random.randint(2, n-1)
        t = k
        while True:
            if t % 2 != 0:
                break
            t //= 2
            x = pow(g, t, n)
            if x > 1 and gmpy2.gcd(int(x-1), int(n)) > 1:
                p = gmpy2.gcd(int(x-1), int(n))
                return (p, n//p)

p, q = divide_pq(e, d, n)

if p>q:
    p,q = q,p
    
list1 = []
num =1
while True:
    flag1 = int(p >> (512 - num))
    if b'flag{' in libnum.n2s(flag1):
        try:
            list1.append(libnum.n2s(flag1).decode())
        except:
            break
    num += 1
flag2 = int(q>>(512-150))
print(list1[-1]+libnum.n2s(flag2).decode())
# flag{e89f47939d12434cb201080d8b240774}

payorder

题目
#!/usr/bin/python3
#coding:utf-8
import time
import string
import random
import signal
from hashlib import sha256
from secret import flag
from base64 import b64encode, b64decode

coins = 1000
sk = ''.join([random.choice(string.printable) for _ in range(random.randint(10, 20))])

flags = [
  ('f', 10), 
  ('l', 10), 
  ('a', 10), 
  ('g', 10), 
  ('fl', 100), 
  ('la', 100), 
  ('ag', 100), 
  ('fla', 1000), 
  ('lag', 1000), 
  ('flag', 10000),
]

def show():
    x = 0
    for name, coin in flags:
        print(f"{x}. {name:4s} -> {coin:6d}")
        x += 1

def order():
    _id = int(input('Which one? '))
    product, price = flags[_id]
    timestamp = int(time.time()*1000000)
    link = f'p={product}&c={price}&t={timestamp}'
    sign = sha256(f'k={sk}&{link}'.encode()).hexdigest()
    link = b64encode(f'{link}&s={sign}'.encode()).decode()
    print(f'Order: {link}')

def pay():
    global coins
    link = b64decode(input('Order: '))
    payments = link.split(b'&')
    assert payments[-1].startswith(b's=') and len(payments[-1]) == 66, "Invalid"

    link, sign = link[:-67], link[-64:]
    signchk = sha256(f'k={sk}&'.encode() + link).hexdigest()
    if signchk.encode() != sign:
        print('Invalid Order!')
        return False

    for payment in payments:
        if payment.startswith(b'p='):
            product = payment[2:].decode()
        if payment.startswith(b'c='):
            coin = int(payment[2:])

    if coins < coin:
        print('Go away you poor bastard!')
        return False

    coins -= coin
    print(f'Your current coins: {coins}')
    print(f'You have bought {product}')
    if product == 'flag':
        print(f'Good job! Here is your flag: {flag}')

def menu():
    funcs = [show, order, pay, exit]
    print("Welcome Flag Store")
    for _ in range(100):
        print(f"Your Coins: {coins}")
        print("1. Show flags")
        print("2. Get order")
        print("3. Pay coin")
        print("4. Bye~")
        funcs[int(input('> ')) - 1]()

if __name__ == "__main__":
    signal.alarm(60)
    menu()
题解

关注如下代码

for payment in payments:
  if payment.startswith(b'p='):
    product = payment[2:].decode()
    if payment.startswith(b'c='):
      coin = int(payment[2:])

也就是说,若我们能实现在已有link后加上&p=flag, 且获得对应的sign,便可以低价购买flag

而为实现这一想法,需要用上哈希长度拓展攻击

当知道hash(secret + message)的值及secret长度的情况下,可以轻松推算出hash(secret + message||padding||m’)。在这里m’是任意数据,||是连接符,可以为空,padding是secret后的填充字节。

from pwn import *
from hashpumpy import hashpump  # https://github.com/bwall/HashPump
import base64

sh = remote('47.97.127.1', 25839)  # nc 47.97.127.1 25839
sh.recvuntil(b'> ')
sh.sendline(b'2')
sh.recvuntil(b'Which one? ')
sh.sendline(b'1')
sh.recvuntil(b'Order: ')
Order = sh.recvline()
Order = base64.b64decode(Order)

# hashpump(hexdigest, original_data, data_to_add, key_length) -> (digest, message)
hexdigest = Order[-64:].decode()
original_data = Order[:-67].decode()
data_to_add = '&p=flag'
for len_sk in range(10, 21):
    sh.sendline(b'3')
    sh.recvuntil(b'Order: ')
    key_length = len_sk + 3  # k={sk}&
    new_hash, new = hashpump(hexdigest, original_data, data_to_add, key_length)
    Order = new+b'&s='+new_hash.encode()
    Order = base64.b64encode(Order)
    sh.sendline(Order)
    tmp = sh.recvline()
    if b'Your current coins: 990' in tmp:
        print(sh.recvline())
        print(sh.recvline())
        # flag{a1dc2134088618c456457dc01e51280e}
        break
    else:
        sh.recvuntil(b'> ')

other

垃圾邮件分析

先过工作量证明,然后肉眼分析是不是垃圾邮件,得解

import hashlib
from string import ascii_letters, digits
from itertools import product
table = ascii_letters + digits
Xnum =4
tail = "tFSZMu4V3cPeYvj14QiMPFpUqLb6"
_hash = "cfa54fcb299c25df405223d0ec0eabeb73f91a4229e3b52b99a6ef7aac567882"
for i in product(table, repeat=Xnum):
    head = ''.join(i)
    # print(head)
    t = hashlib.sha256((tail + head).encode()).hexdigest()
    if t == _hash:
        print('爆破成功!结果是:', end='')
        print(head)

交互

(base) 0HB@Caliburn ~ % nc 47.97.127.1 26120
sha256(tFSZMu4V3cPeYvj14QiMPFpUqLb6 + xxxx) = cfa54fcb299c25df405223d0ec0eabeb73f91a4229e3b52b99a6ef7aac567882
xxxx = KiYX

         ### #### ####   ###### ####### ######  
        ## ## ##   ##    # ## #  ##   #  ##  ## 
         #    ##   ##      ##    ## #    ##  ## 
       ####   ##   ##      ##    ####    #####  
        ##    ##   ##   #  ##    ## #    ## ##  
        ##    ##   ##  ##  ##    ##   #  ##  ## 
       ####  #### ####### ####  ####### #### ## 


       1. In this challenge, you are required to classify a
          bunch of e-mail texts into ham/spam categories
       2. You will recive 50 samples as the training data
       3. And I will give you 10 samples to validate your
          trained model
       4. Solve them to win the flag!

Press ENTER to continue... 
################################################################################
Training data 1/50: SPAM
--------------------------------------------------------------------------------
b"Subject: bait - excelled @ em . ca when can you start\r\n+ unable to see graphics ? please go here to view this email . +\r\nhi\r\nbait - excelled @ em . ca ,\r\nyour name was given to us as someone who might be interested in getting\r\nout of the rat race . are you really ?\r\nif so , keep reading ! being in charge of yourself and your life is the only\r\nway to go .\r\nthere are literally thousands of us who are making a good living at home\r\non the internet , and there ' s no reason why you can ' t be one of us . and i ' m\r\ntalking about a legitimate business you can be proud of .\r\njust visit our site when you have a minute ,\r\nand you ' ll know right away if this is what you ' ve been searching for .\r\nlooking forward to helping you get out of the rat race !\r\ntake care !\r\nif you would prefer not to receive email advertisements from this advertiser in the future , visit us here .\r\n+ + + + +\r\nthe preceding advertisement was sent from sweepsatstake . com .\r\nif you would like to stop receiving advertisements from sweepsatstake . com in the future , please\r\n+ + + + +\r\n"
Press ENTER to continue... 
################################################################################
Training data 2/50: SPAM
--------------------------------------------------------------------------------
b'Subject: re : 63 % - off \\ / iagra , cialis , ambien , soma and other drugs hamster disputing\r\ncentroid terminates benzedrine boggled zebra\r\nvenn disengaging inferiors burdensome tortoise\r\nconfusing congenial ires named\r\nbeater absorbing boundlessness\r\nbetterments popsicles david stud enlarges\r\nleaflets delphinus pickering participle'
Press ENTER to continue... 


......


Press ENTER to continue... 
################################################################################


......


Testing data 9/10
--------------------------------------------------------------------------------
b"Subject: fwd : need meds xanaix | = v @ 1 | um ' vl @ gra pnter : m : in _ somia | hooso\r\nwe believe ordering medication should be as simple as ordering anything else on the internet : private , secure , and easy .\r\nwe have : ` som : a : # pntermin . vl @ gra = / v / alium _ xana _ x _ - ativ ` @ n\r\nplus : p : @ xil , busp @ : r , a ` dipex , ionam | * n , m 3 rid ` ia , x 3 nic . a | , ambi 3 ' n , s : 0 nata , fl 3 x . eril , ce | : 3 brex , f ' ioric 3 t , tram : @ do | , uitr @ ` m , l 3 . vitra , prop . 3 cia , ac . yc | 0 vir , pr ` 0 z @ c\r\nwe offer you a choice of original and generic medications .\r\nenjoy deep discount meds here .\r\n"
The category is (H for ham/S for spam): 
S
################################################################################
Testing data 10/10
--------------------------------------------------------------------------------
b'Subject: get your college degree online !\r\n'
The category is (H for ham/S for spam): 
S
################################################################################

        Good job! Just take it:
        flag{3acf10d4ed12d34ed63e62ec225c077f}

Press ENTER to continue... %                                                    (base) 0HB@Caliburn ~ % 

文字频率分析

题目
import os
import random
import base64
import time
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import io
from secret import flag
import hashlib


def pow(hard_level=6):
    if hard_level >= 30:
        hard_level = 30

    m = hex(random.getrandbits(16 * 8))[2:]
    c = hashlib.md5(m.encode()).hexdigest()
    part = m[:32 - hard_level]
    print(f'plaintext: {part}' + '?' * hard_level)
    print(f'md5_hex -> {c}')
    return part, c


def crack(part, c, level=6):
    s = int(part, 16) << (level * 4)
    _limit = s + (1 << level * 4)
    while s <= _limit:
        s += 1
        seed = hex(s)[2:].encode()
        if hashlib.md5(seed).hexdigest() == c:
            return seed


def getData(nums=400):
    data = []
    result = [0 for _ in range(26)]
    for i in range(nums):
        c = random.randint(0, 25)
        data.append(c)
        result[c] += 1
    result = [str(i) for i in result]
    return data, result


def makeImage(data=[], size=20):
    img = Image.new('RGB', (size * 50, size * 50))
    for y in range(size):
        for x in range(size):
            img.paste(pngs[data[x + y * size]], (x * 50, y * 50))  # 怀疑写反了
    content = io.BytesIO()
    img.save(content, 'png')
    img.save('flag.png')
    img.close()
    return content.getvalue()


def game():
    print("Easy pow:")
    pm, c = pow()
    m = input("What's is plaintext?\n> ")
    if hashlib.md5(m.encode()).hexdigest() != c:
        print('Failed')
        return

    data, result = getData()
    png = makeImage(data)
    print('now, you get a png: ')
    print(base64.b64encode(png).decode())
    print("##The end, please tell me your list:")
    _start = time.time()
    _input = input('> ').split(',')
    _end = time.time()

    if _end - _start > 10:
        print('timeouted')
        return

    if _input == result:
        print("Got it!")
        print(flag)
    else:
        print('Sorry, try again.')


if __name__ == '__main__':
    print('loading pngs, please waiting...')
    pngs = []
    seed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    for i in range(26):
        pngs.append(Image.open(f'/app/src/{seed[i]}.png').resize((50, 50), Image.ANTIALIAS))
    game()
题解
Step1

先交互,得到一张有400个字符串的png大图(test.png)
test

分割png,去重得到26个字母,根据密码表肉眼识别后手动改名为对应字母

from PIL import Image, ImageDraw, ImageFont, ImageFilter


size = 20
imgs = []
png = Image.open('/Users/0HB/Desktop/分析/test.png')
pngs = []

for y in range(size):
    for x in range(size):
        tmp = png.crop((x * 50, y * 50, (x+1)*50, (y+1) * 50))
        if tmp not in pngs:  # 去重
            pngs.append(tmp)

assert len(pngs) == 26
for i in range(len(pngs)):
    pngs[i].save(f'/Users/0HB/Desktop/分析/seeds/{i}.png')

密码表

seeds

Step2

再次交互,将得到新的大图分割成400份,每一份都在26个字母图中查在哪个位置,即可分别识别出对应字母

最后仿照题目中result列表的生成方式,恢复出result,发送之得到flag

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from string import digits
from pwn import *
from itertools import product
import base64, hashlib
from PIL import Image

table = 'abcdef' + digits


class Solve():
    def __init__(self):
        # nc 47.97.127.1 24929
        self.sh = remote('47.97.127.1', 24929)

    def proof_of_work(self):
        GeShi = b"What's is plaintext?"
        proof = self.sh.recvuntil(GeShi).decode().split('sha256')[-1].split("What's is plaintext?")[0]
        print(proof)
        Xnum = 6
        tail = proof.split('plaintext: ')[-1].split('??????')[0].strip()
        _hash = proof.split('-> ')[-1].strip()
        if '\n' in _hash:
            _hash = _hash.split('\n')[0]
        print("未知数:", Xnum)
        print(tail)
        print(_hash)
        print('开始爆破!')
        for i in product(table, repeat=Xnum):
            head = ''.join(i)
            # print(head)
            t = hashlib.md5((tail+head).encode()).hexdigest()
            if t == _hash:
                print('爆破成功!结果是:', end='')
                print(tail+head)
                self.sh.sendline((tail+head).encode())
                break

    def fxxk(self):
        size = 20
        seed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        result = [0 for _ in range(26)]
        ans = []

        for i in seed:
            path = f'/Users/0HB/Desktop/分析/seeds/{i}.png'
            ans.append(Image.open(path).resize((50, 50), Image.ANTIALIAS))  # .resize((50, 50), Image.ANTIALIAS) 很关键

        png = Image.open('/Users/0HB/Desktop/分析/flag.png')
        for y in range(size):
            for x in range(size):
                tmp1 = png.crop((x * 50, y * 50, (x + 1) * 50, (y + 1) * 50))
                c = ans.index(tmp1)
                result[c] += 1
        return result

    def solve(self):
        self.proof_of_work()
        self.sh.recvuntil(b'now, you get a png:')
        tmp = self.sh.recvuntil(b'##The end, please tell me your list:').split(b'##The end, please tell me your list:')[0]
        tmp = tmp.strip()
        img_data = base64.b64decode(tmp)
        with open('/Users/0HB/Desktop/分析/flag.png', 'wb') as f:
            f.write(img_data)
        print('图片已生成!')
        self.sh.recvuntil(b'> ')
        result = str(self.fxxk())[1:-1].replace(' ', '').encode()
        print(result)
        self.sh.sendline(result)
        print(self.sh.recvline())
        print(self.sh.recvline())
        # flag{cedf7a5c55e775f73080357b358af0ac}


if __name__ == '__main__':
    solution = Solve()
    solution.solve()

Misc

空投之王

题解

题目给出日志文件,要求找到Airdrop发送者的手机号。

搜索,找到资料通过分析iOS 15中的sysdiagnose日志确定AirDrop数据的发送电话号码

通过爆破在接收苹果设备的系统诊断日志中发现的部分SHA256哈希条目来获得发件人的电话号码

根据文章,又因为笔者使用的是MacOS,非常方便地找到并打开了system_logs.logarchive

筛选好时间、进程类型以及关键词(Phone=[),有如下:

在这里插入图片描述

[58299...893d4]
[58299...e18e4]
[11cbd...893d4]
[11cbd...e18e4]
[fade7...e461b]

这里泄漏出来了电话号码sha256后,前六位以及末六位的值,接下来只需写脚本爆破即可。

思路通了,但Python爆的着实有·慢,最后队里Mu.Chen师傅利用已有取证工具一把梭了…

彳亍,那么便没再做研究了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值