Guangdong Strong Net Cup

1: Beautiful memories

Open the source code file and read that we found that the encryption algorithm is CBC, the encryption mode is CBC mode, and the encryption is 8 bits long, as shown in the figure below

We know that the plaintext at the beginning is "have a good time" and the encrypted ciphertext, that is, plaintext1, plaintext2 and all ciphertexts are known, so we can get ciphertext2 = ciphertext1 ^ plaintext2 ^ key, then key = ciphertext2 ^ ciphertext1 ^ plaintext2 At this time, we can get plaintext [i] = ciphertext [i-1] ^ ciphertext [i] ^ key, so that all plaintext can be solved. The source code is as follows:

def xor(data,key):
	return bytes([x ^ key[i%len(key)] for i, x in enumerate(data)])

with open('flag.txt.encrypted', 'rb') as f:
	s=f.read()
s1="have a good time".encode()
c1=s[:8]
c2=s[8:16]
c3=s[16:24]
key=xor(xor(c1,s1[8:]),c2)
print(key)
m1=xor(xor(c2,key),c3)
sssssss=""
for i in range(8,len(s)-8,8):
	m1=xor(xor(s[i:i+8],key),s[i+8:i+16])
	sssssss=sssssss+m1.decode('utf-8')

print(sssssss)

2: Sad ending

The same as the encryption principle of the previous question, but we get the ending plain text "keep away from xiaocui!", But we have padding in the encryption process, we do n’t know the penultimate plain text in the encryption, the penultimate paragraph What is the plain text, we can guess the padding is 0-7 (according to the encryption principle), try to guess the padding of different lengths to get the key and then decrypt and verify, get the real key, decrypt

def xor(data,key):
	return bytes([x ^ key[i%len(key)] for i, x in enumerate(data)])

with open('flag.txt.encrypted', 'rb') as f:
	s=f.read()
BLOCK_SIZE=8
s1="keep away from xiaocui!".encode()
c1=s[-16:-8]
c2=s[-24:-16]
c3=s[-32:-24]
keylist=[]
for i in range(8):
	m1=s1[i+8:i+16]
	keylist.append(xor(xor(c1,m1),c2))

key=b""
for i in range(8):
	mm=xor(xor(c2,keylist[i]),c3)
	if mm==s1[i:i+8]:
		key=keylist[i]

print(key)
sssssss=""
for i in range(8,len(s)-8,8):
	m1=xor(xor(s[i:i+8],key),s[i+8:i+16])
	sssssss=sssssss+m1.decode('utf-8')

print(sssssss)

3. The lost secret

We got the incomplete RSA public key and private key, that is, the n, p, q and other parameters in the file are incomplete. Searching and we find https://www.40huo.cn/blog/rsa-private-key-recovery The questions in -and-oaep.html are similar to our current questions, but our n is not complete and the low order does not exist. But the low bits of p and q exist, so we can use the low bits of p and q to calculate the low bits of n, that is, 0x8b * 0x05 = 0x2b7. We can put 'b7' at the end of n to complete n, then we use the above script Can solve p, q and private key

#!/usr/bin/python
#-*- coding:utf-8 -*-

import re
import pickle
from itertools import product
from libnum import invmod, gcd


def solve_linear(a, b, mod):
    if a & 1 == 0 or b & 1 == 0:
        return None
    return (b * invmod(a, mod)) & (mod - 1)  # hack for mod = power of 2


def to_n(s):
    s = re.sub(r"[^0-9a-f]", "", s)
    return int(s, 16)


def msk(s):
    cleaned = "".join(map(lambda x: x[-2:], s.split(":")))
    return msk_ranges(cleaned), msk_mask(cleaned), msk_val(cleaned)


def msk_ranges(s):
    return [range(16) if c == " " else [int(c, 16)] for c in s]


def msk_mask(s):
    return int("".join("0" if c == " " else "f" for c in s), 16)


def msk_val(s):
    return int("".join("0" if c == " " else c for c in s), 16)


E = 65537

N = to_n("""00:c4:9d:36:a4:77:76:12:12:85:24:6c:74:1d:7d:
   b3:ce:f4:c3:a4:69:cd:0b:2e:8f:d6:75:e3:80:b8:
   e8:1c:ce:e8:60:90:45:56:73:ab:32:32:00:7f:6a:
   76:3e:b6:10:d3:a2:74:da:f9:4e:a5:7e:ae:ef:f4:
   da:82:57:6d:68:82:50:d8:b1:fc:92:b1:5c:7d:54:
   f5:7e:d0:06:8a:60:ff:82:70:72:20:68:4b:71:ba:
   87:44:57:c1:97:a0:8a:2d:53:93:f3:0a:60:87:a3:
   85:c8:45:e6:0a:88:85:b5:ff:c7:09:9a:76:03:fe:
   99:b6:fb:8a:1e:9f:a8:42:3a:0a:c9:a9:bf:1c:87:
   2c:c4:99:10:db:46:e3:a9:a5:79:93:8c:75:71:ec:
   c6:3b:af:44:dc:60:c4:53:f6:3c:e8:73:2f:50:10:
   38:e7:6f:d0:a5:4b:ae:e3:1e:43:11:42:2c:a2:38:
   e6:3f:0b:13:54:63:e8:2f:9e:61:ab:08:65:97:e0:
   27:30:19:fd:a7:fe:5c:d8:11:b8:34:87:ad:02:c2:
   bc:cd:73:d3:86:be:fd:2a:b4:fe:7d:7e:d3:64:bb:
   6f:63:ed:a6:1d:ee:f2:80:da:9d:7a:23:7f:c1:39:
   b0:98:0c:85:8f:d0:4b:9f:e4:1a:26:fc:44:d1:67:
   03:32:03:0c:91:61:23:4c:81:6f:42:18:88:41:dc:
   27:55:a3:07:7c:a1:ad:f3:58:4d:91:07:65:f1:63:
   f2:34:d5:17:0e:59:c6:bb:b6:6d:7d:0c:d2:64:4b:
   b9:9c:52:59:03:8e:2a:43:23:76:33:c3:e8:72:3b:
   1c:e0:40:97:36:5f:ae:00:d7:e3:09:eb:df:55:44:
   22:b4:09:00:b5:09:41:70:6c:5c:3b:98:d3:34:7e:
   60:a2:b8:93:bd:af:32:77:48:48:8a:a5:9c:0e:6a:
   a1:79:36:86:8c:e9:3f:b1:a2:a7:4a:3a:d8:d6:f6:
   dd:62:d8:ae:9e:13:bb:0c:6b:b1:65:68:0d:7e:58:
   3f:68:1e:91:49:13:19:68:2b:fd:3c:5e:52:fa:76:
   b0:57:fc:0e:35:d8:71:56:41:06:ef:50:99:56:dd:
   d4:9a:1f:d3:46:26:12:9c:15:4b:43:fc:1b:de:c9:
   06:ad:82:56:63:c8:a4:83:32:d2:35:05:23:15:52:
   d9:0a:73:85:5e:c9:c2:56:af:69:d2:5f:77:04:28:
   c8:4c:b9:a6:d4:15:15:b5:15:99:13:ef:a9:a5:de:
   5a:74:b1:03:cf:32:a5:03:69:f8:e9:bb:7e:16:31:
   5e:43:e7:02:51:ac:c5:f6:bf:ef:1c:74:f7:13:0c:
   19:ad:b7""")

p_ranges, pmask_msk, pmask_val = msk("""00:  :05:89:  :bd:35:  :  :23:  :  :  :  :84:
      :  :ed:  :70:14:  :  :  :10:  :  :87:  :51:
    ea:  :97:69:  :52:  :  :  :  :  :ea:  :  :15:
      :  :34:  :be:11:23:  :  :34:14:  :94:  :10:
      :  :74:87:37:ee:81:62:ee:95:  :  :dc:49:dd:
      :  :35:  :81:  :fa:  :  :  :86:  :  :  :fb:
      :93:  :  :12:  :14:  :ab:76:  :96:  :  :27:
      :21:  :04:01:41:  :98:  :ff:  :  :12:dc:  :
    cd:  :39:95:30:  :47:  :fa:ff:  :34:  :ad:  :
      :52:02:fa:bc:14:22:22:48:61:62:bd:53:  :  :
    72:08:cb:41:88:  :  :  :63:91:30:fe:  :  :42:
    87:  :18:52:  :39:dd:  :68:  :fe:06:88:81:  :
      :  :  :ae:fd:  :  :fb:21:37:59:  :53:  :fa:
      :07:40:eb:33:77:51:64:10:dd:  :73:  :86:62:
      :bf:  :79:  :34:  :bb:  :44:ff:  :46:fe:90:
    ef:  :52:ad:  :  :fe:  :69:18:89:bd:cd:09:46:
      :  :74:71:  :  :  :41:66:  :  :11:  :25:  :
    39:8b""")

q_ranges, qmask_msk, qmask_val = msk(""" 00:ce:43:ef:  :76:58:17:43:31:  :  :32:70:  :
    89:  :  :36:55:06:  :79:66:78:  :  :  :  :  :
      :85:  :  :  :  :  :33:bb:  :  :56:  :66:cb:
      :08:  :  :90:cb:  :  :24:fa:ca:47:  :  :  :
      :88:  :83:01:  :62:  :  :  :  :  :  :ad:ae:
      :  :  :58:  :ec:  :  :  :09:04:86:  :05:00:
      :df:50:84:81:80:  :ae:  :24:  :94:da:  :04:
    ce:  :ef:  :  :ed:be:bf:43:78:  :  :05:93:  :
    08:52:05:  :  :  :  :ae:  :  :  :  :ab:  :  :
      :76:ce:  :  :  :  :19:bd:22:  :ef:dc:bf:ea:
    ab:78:01:  :  :85:  :  :  :ea:  :  :fb:  :  :
    92:66:19:  :  :ab:  :  :82:  :  :31:  :  :da:
    82:  :13:82:43:  :  :94:13:41:  :  :  :37:  :
      :04:56:02:87:dd:  :58:27:  :  :24:  :  :  :
    28:  :  :09:14:89:  :  :  :49:59:  :16:eb:65:
      :01:22:  :  :dd:  :78:  :  :db:90:  :ac:  :
      :fd:  :03:74:  :  :  :  :92:  :00:ba:  :  :
      :05""")

_, dmask_msk, dmask_val = msk("""11:  :  :69:62:64:  :  :  :  :15:  :13:de:de:
    cf:  :  :17:  :  :75:  :98:42:fc:  :12:15:08:
      :  :  :  :  :36:  :be:25:48:  :  :19:  :  :
      :47:11:19:  :03:  :49:fc:da:  :96:45:eb:  :
      :  :  :91:  :ea:  :  :55:ff:  :37:58:  :  :
    19:  :  :73:40:  :91:15:01:da:91:22:fd:32:  :
      :  :50:  :  :66:  :  :  :42:  :  :ef:  :  :
    df:42:  :97:30:  :39:  :  :  :  :  :  :dc:  :
      :  :  :  :  :38:  :  :  :88:28:  :05:  :  :
    78:59:fa:  :86:  :19:24:  :  :  :  :da:cf:15:
    39:  :  :  :  :ef:55:  :ce:47:  :58:89:  :fb:
      :24:  :  :  :92:  :  :ee:  :  :db:67:31:ce:
      :28:  :72:ec:89:  :04:  :  :50:  :  :  :  :
      :37:  :44:  :  :  :  :56:  :38:  :bb:47:bb:
    66:83:99:22:07:72:  :  :48:52:02:  :  :  :29:
      :82:56:  :67:  :95:  :  :56:94:  :  :71:  :
    bf:27:98:  :  :54:98:26:06:87:  :ae:  :53:be:
      :  :80:37:60:61:ea:ef:de:  :  :df:90:81:  :
    70:  :06:33:26:  :75:fe:95:  :92:  :78:cd:05:
    64:cc:68:  :  :36:54:  :bd:16:90:ee:60:  :  :
      :  :41:  :  :91:  :79:58:06:50:  :46:  :  :
    45:  :09:ca:ac:16:  :27:98:  :  :ba:82:  :77:
    93:98:ad:  :15:  :67:53:97:ad:ee:50:44:  :31:
    07:  :ff:01:  :09:  :  :  :  :  :46:  :  :42:
    15:  :db:df:42:be:  :  :  :78:  :41:  :  :  :
      :14:  :  :25:fc:  :84:  :  :  :  :  :  :20:
    da:46:01:eb:87:  :12:57:  :  :56:af:  :87:93:
    60:  :02:  :18:89:63:72:ad:  :ed:cf:  :  :84:
      :22:  :13:  :  :dd:  :ff:  :  :  :de:62:37:
      :19:66:  :  :86:02:  :38:  :  :  :  :ec:14:
    12:  :43:93:19:65:98:  :  :03:  :  :  :ef:  :
      :  :ca:07:92:22:  :  :bb:15:eb:  :  :  :35:
      :72:29:cd:  :  :99:  :  :  :  :41:06:  :  :
      :43:33:  :32:  :  :54:be:92:62:  :78:59:42:
    79:89""")

_, dpmask_msk, dpmask_val = msk("""  :39:  :28:16:02:89:ce:11:fe:  :  :  :  :af:
      :  :  :ed:97:  :  :11:20:ba:ae:98:ad:  :  :
      :10:87:ac:07:  :  :  :  :50:  :  :70:50:52:
    df:89:eb:02:  :  :  :  :93:11:  :  :12:  :56:
      :08:  :  :ea:  :10:fa:19:  :  :  :54:45:07:
      :  :bc:ff:33:  :db:63:49:fe:52:  :33:  :  :
    bf:cd:45:91:  :10:  :  :92:81:40:03:  :80:  :
    29:  :30:  :ed:43:64:ca:  :bf:64:  :  :bf:  :
      :  :  :24:72:84:  :  :ff:  :  :24:  :81:27:
    db:23:  :64:  :67:  :ba:  :  :bc:  :  :  :  :
      :ae:88:  :  :  :  :  :91:  :  :14:  :ba:ef:
      :89:  :  :  :  :  :  :  :  :05:  :75:52:  :
      :  :  :be:ad:df:  :02:88:00:  :  :15:45:  :
    cf:32:  :ca:  :93:  :32:  :40:  :27:dd:  :19:
    73:dc:  :  :  :  :  :cf:  :  :dd:  :  :ca:  :
    ee:  :ca:  :  :  :49:  :27:  :58:53:  :64:25:
      :22:06:16:ff:62:bc:  :  :  :  :24:fc:  :  :
    df""")

_, dqmask_msk, dqmask_val = msk("""02:  :bd:  :19:25:98:75:  :65:  :55:28:33:bc:
    34:84:91:01:96:  :  :08:  :32:45:  :27:  :  :
      :fe:  :bb:63:32:68:  :51:bd:75:40:  :52:52:
      :  :  :78:85:fc:94:  :07:  :14:  :  :  :  :
    15:dd:  :  :93:  :01:  :  :77:ca:  :40:  :da:
      :89:bc:87:62:dc:ac:61:88:  :  :70:  :69:  :
      :36:  :  :21:08:  :dc:73:  :ad:da:ee:fe:  :
    96:  :58:  :  :46:  :29:ff:97:ce:  :  :  :cb:
    51:  :  :81:  :22:  :  :19:  :10:69:41:36:ca:
      :22:49:  :cc:cf:06:  :  :08:  :76:  :  :45:
    98:  :  :45:  :  :  :69:13:65:  :  :da:54:  :
    19:  :ee:24:  :73:  :  :  :  :  :  :18:53:40:
    21:25:  :  :84:52:cd:  :49:33:78:  :  :ed:  :
    25:27:  :  :  :ca:  :  :  :ca:  :  :bc:  :02:
    31:70:  :10:ca:84:59:  :  :  :52:  :27:76:  :
    47:  :66:bf:ff:  :03:  :99:ff:  :df:  :  :  :
      :46:27:45:  :65:07:  :48:da:dc:  :80:  :  :
    f9""")


def search(K, Kp, Kq, check_level, break_step):
    max_step = 0
    cands = [0]
    for step in range(1, break_step + 1):
        #print " ", step, "( max =", max_step, ")"
        max_step = max(step, max_step)

        mod = 1 << (4 * step)
        mask = mod - 1

        cands_next = []
        for p, new_digit in product(cands, p_ranges[-step]):
            pval = (new_digit << ((step - 1) * 4)) | p

            if check_level >= 1:
                qval = solve_linear(pval, N & mask, mod)
                if qval is None or not check_val(qval, mask, qmask_msk, qmask_val):
                    continue

            if check_level >= 2:
                val = solve_linear(E, 1 + K * (N - pval - qval + 1), mod)
                if val is None or not check_val(val, mask, dmask_msk, dmask_val):
                    continue

            if check_level >= 3:
                val = solve_linear(E, 1 + Kp * (pval - 1), mod)
                if val is None or not check_val(val, mask, dpmask_msk, dpmask_val):
                    continue

            if check_level >= 4:
                val = solve_linear(E, 1 + Kq * (qval - 1), mod)
                if val is None or not check_val(val, mask, dqmask_msk, dqmask_val):
                    continue

                if pval * qval == N:
                    print "Kq =", Kq
                    print "pwned"
                    print "p =", pval
                    print "q =", qval
                    p = pval
                    q = qval
                    d = invmod(E, (p - 1) * (q - 1))
                    coef = invmod(p, q)

                    from Crypto.PublicKey import RSA
                    print RSA.construct(map(long, (N, E, d, p, q, coef))).exportKey()
                    quit()

            cands_next.append(pval)

        if not cands_next:
            return False
        cands = cands_next
    return True



def check_val(val, mask, mask_msk, mask_val):
    test_mask = mask_msk & mask
    test_val = mask_val & mask
    return val & test_mask == test_val


# K = 4695
# Kp = 15700
# Kq = 5155

for K in range(1, E):
    if K % 100 == 0:
        print "checking", K
    if search(K, 0, 0, check_level=2, break_step=20):
        print "K =", K
        break

for Kp in range(1, E):
    if Kp % 1000 == 0:
        print "checking", Kp
    if search(K, Kp, 0, check_level=3, break_step=30):
        print "Kp =", Kp
        break

for Kq in range(1, E):
    if Kq % 100 == 0:
        print "checking", Kq
    if search(K, Kp, Kq, check_level=4, break_step=9999):
        print "Kq =", Kq
        break

We get p, q, c, we can easily solve the plain text

import gmpy2
def shuchu(mingwenstr):
    if mingwenstr[len(mingwenstr)-1]=='L':
        mingwenstr=mingwenstr[2:len(mingwenstr)-1]
    else:
        mingwenstr=mingwenstr[2:len(mingwenstr)]
    if not len(mingwenstr)%2==0:
            mingwenstr='0'+mingwenstr
    i=len(mingwenstr)
    mingwen=""
    while i>=1:
        str1=mingwenstr[i-2:i]
        if int(str1,16)>33 and int(str1,16)<126:
            mingwen=chr(int(str1,16))+mingwen
        else :
            mingwen=" "+mingwen
        i=i-2
    print mingwen
p = 30804877236372761296348297513767908130120426767441642194038947059431749919743933282721728129660558520306627781991434638545287122418576024822599938752655436891429241798416041881441469038271460545196755187872022209260074336340748692939443634393492611052850561312058115000234467417922716845989845380178291512893577636848676778152648705150749219629638913963012345388388992649857974643758097581431795569765569985118215469798809551704275008726932734117893757436777110974529289423114881289423038562352073193732977840168067817149865622380253870276206212656648830136975036452877460473463818007722056777837507566352911184181643
q = 26038591288856688238001759665609016744197175469090080494077820415283745172609947555684568450035539489682168553390403854805974969118763740560638548072896648612347287461822059996717273680094814363090434263883250281614203478279438635312321752371517752177819983938115532573238089291708699056464231184039223531822571471611431921747169774540943776543504663419138030516108434288911593973010680364553026970545232818747951718950151516127319881685156986937644295056292836729469548074713781625918117631575942194589642230959265894967721587381648790905383499092379075578245308113268969812469233669312409066969648987454629639842309
n=0xc49d36a47776121285246c741d7db3cef4c3a469cd0b2e8fd675e380b8e81ccee86090455673ab3232007f6a763eb610d3a274daf94ea57eaeeff4da82576d688250d8b1fc92b15c7d54f57ed0068a60ff82707220684b71ba874457c197a08a2d5393f30a6087a385c845e60a8885b5ffc7099a7603fe99b6fb8a1e9fa8423a0ac9a9bf1c872cc49910db46e3a9a579938c7571ecc63baf44dc60c453f63ce8732f501038e76fd0a54baee31e4311422ca238e63f0b135463e82f9e61ab086597e0273019fda7fe5cd811b83487ad02c2bccd73d386befd2ab4fe7d7ed364bb6f63eda61deef280da9d7a237fc139b0980c858fd04b9fe41a26fc44d1670332030c9161234c816f42188841dc2755a3077ca1adf3584d910765f163f234d5170e59c6bbb66d7d0cd2644bb99c5259038e2a43237633c3e8723b1ce04097365fae00d7e309ebdf554422b40900b50941706c5c3b98d3347e60a2b893bdaf327748488aa59c0e6aa17936868ce93fb1a2a74a3ad8d6f6dd62d8ae9e13bb0c6bb165680d7e583f681e91491319682bfd3c5e52fa76b057fc0e35d871564106ef509956ddd49a1fd34626129c154b43fc1bdec906ad825663c8a48332d23505231552d90a73855ec9c256af69d25f770428c84cb9a6d41515b5159913efa9a5de5a74b103cf32a50369f8e9bb7e16315e43e70251acc5f6bfef1c74f7130c19adb7
assert n==p*q
e=65537

fi=open("flag.txt.en","rb")
miwen=fi.read()
fi.close()

miwenhex=miwen.encode("hex")
miwenint=int(miwenhex,16)
d=gmpy2.invert(e,(p-1)*(q-1))
mingwen=pow(miwenint,d,n)
print len(hex(mingwen)[2:])
print shuchu(hex(mingwen))

4. Pharaoh's Secret

According to the title, we guess that this is a key sharing problem

from secretsharing import PlaintextToHexSecretSharer
flags=['1-fddc7d57594928fb74a507ab9cba0b28b92bb6e7b36a9925a105eeddac020e64','3-84f82314003c9690eeacd823b22680ccbe93ac098cabdd0a992c095dde0031cf','5-b0e2e8d2cadc91f8f2f357a42e26aeabaccbfa7731437298ca23d8a4a5424ce4','7-810e7545213971a3c7c2dce3d0998764d0bc1e3b866b15ad0deebaa7abcf64c5','9-b4da0bd03394e4bdfef92f16365e8811d9614f11b99111bcf8a4e68ba79626a2','b-661069e7d491719759a3199be1f65ffb6db92d1b014abb4e33ca7e32f85ee276','d-1f84ab9b467a4ec4de4451ed187987785b567bbdde0126d0722e3335a5307d68','f-9001dc36dd28c5c5dd7333968e7263986f55dd79cd9be286d21f45e46f53c399']

print PlaintextToHexSecretSharer.recover_secret(flags[0:8])

5. Perfect error

According to the title "Encoding to avoid character confusion", I guess this is a base58 encoding, but the difference is the encoding character order of base58. The character order of this question is "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789", so we directly put the alphabet in base58.py under the python library Change to alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789', then decrypt the ciphertext 'RJv9mjS1bM9MZafGV77uTyDaapNLSk6t358j2Mdf1pbCByjEiVpX'

Published 43 original articles · Like 23 · Visits 30,000+

Guess you like

Origin blog.csdn.net/zhang14916/article/details/100726269