
풀이
문제 파일에 함수 main을 디컴파일 해보면
이 코드를 위에서부터 해석해보면
1. 변수 v6에 랜덤한 값을 할당한다.
2. 사용자에게 입력 받은 문자열을 변수 v7에 저장한다.
3. v6와 v7을 XOR 연산하여 8자리 16진수를 변수 s에 저장한다.
4. 변수 s에 들어있는 문자열을 뒤집어 변수 s1에 저장한다.
5. 만약 변수 s1에 들어있는 값이 'a0b4c1d7'과 동일하다면 플래그를 출력한다.
이 순서를 반대로 생각하여 우리가 변수 v7에 입력해야할 값을 찾아보겠다.먼저 반대로 생각해보면
1. 'a0b4c1d7'을 뒤집는다. 즉 변수 s1이 '7d1c4b0a'가 되어야한다.
2. 16잔수에서 정수로 v6과 v7을 XOR 연산한다. 따라서 2095886858이라는 키 값이 나온다.
3. V7 = v6 ^ 2095886858 이므로 이 식을 계산하는 프로그램을 통해 입력해야할 값을 추측해보겠다.

풀이
문제 파일에 함수 main을 디컴파일 해보면
if 조건문에서 참이 반환될 시에 Correct를 출력한다.
조건은 strcmp를 이용해 "Compar3_the_str1ng"과 동일한 문자열이 입력될 경우,
참을 반환한다.

풀이
문제 파일에 함수 main을 디컴파일 해보면
함수 sub_140001000을 들어가보면_BOOL8 __fastcall sub_140001000(_BYTE *a1) { if ( *a1 != 67 ) return 0; if ( a1[1] != 111 ) return 0; if ( a1[2] != 109 ) return 0; if ( a1[3] != 112 ) return 0; if ( a1[4] != 97 ) return 0; if ( a1[5] != 114 ) return 0; if ( a1[6] != 51 ) return 0; if ( a1[7] != 95 ) return 0; if ( a1[8] != 116 ) return 0; if ( a1[9] != 104 ) return 0; if ( a1[10] != 101 ) return 0; if ( a1[11] != 95 ) return 0; if ( a1[12] != 99 ) return 0; if ( a1[13] != 104 ) return 0; if ( a1[14] != 52 ) return 0; if ( a1[15] != 114 ) return 0; if ( a1[16] != 97 ) return 0; if ( a1[17] != 99 ) return 0; if ( a1[18] != 116 ) return 0; if ( a1[19] != 51 ) return 0; if ( a1[20] == 114 ) return a1[21] == 0; return 0; }모든 아스키코드 값이 만족할 경우 참이 반화되기 때문에 이를 역으로 출력하는 코드를 작성하면 플래그 값을 얻을 수 있다.
풀이코드 없이 조건 아스키코드 값들을 문자열로 변환한 후 제출했다.
풀이
배열 aC와 비교하여 똑같은 값인지 파악한다.
aC에 들어있는 값을은 다음과 같다.
이 문자열과 일치할 경우 Correct를 출력한다..data:0000000140003000 aC db 'C',0 .data:0000000140003002 align 4 .data:0000000140003004 aO db 'o',0 .data:0000000140003006 align 8 .data:0000000140003008 aM db 'm',0 .data:000000014000300A align 4 .data:000000014000300C aP db 'p',0 .data:000000014000300E align 10h .data:0000000140003010 a4 db '4',0 .data:0000000140003012 align 4 .data:0000000140003014 aR db 'r',0 .data:0000000140003016 align 8 .data:0000000140003018 aE db 'e',0 .data:000000014000301A align 4 .data:000000014000301C db '_',0 .data:000000014000301E align 20h .data:0000000140003020 aT db 't',0 .data:0000000140003022 align 4 .data:0000000140003024 db 'h',0 .data:0000000140003026 align 8 .data:0000000140003028 aE_0 db 'e',0 .data:000000014000302A align 4 .data:000000014000302C db '_',0 .data:000000014000302E align 10h .data:0000000140003030 aA db 'a',0 .data:0000000140003032 align 4 .data:0000000140003034 aR_0 db 'r',0 .data:0000000140003036 align 8 .data:0000000140003038 aR_1 db 'r',0 .data:000000014000303A align 4 .data:000000014000303C a4_0 db '4',0 .data:000000014000303E align 20h .data:0000000140003040 aY db 'y',0풀이코드 없이 문자열을 조합해서 제출헀다.
풀이
XOR 연산을 통해 'A ^ B = C 라면 C ^ B = A 와 C ^ A = B 가 성립' 이라는 조건을 가지고
byte_140003000의 값과 입력한 a1의 값을 계산한다..data:0000000140003000 byte_140003000 db 49h, 60h, 67h, 74h, 63h, 67h, 42h, 66h, 80h, 78h, 2 dup(69h) .data:0000000140003000 ; DATA XREF: sub_140001000+28↑o .data:000000014000300C db 7Bh, 99h, 6Dh, 88h, 68h, 94h, 9Fh, 8Dh, 4Dh, 0A5h, 9Dh .data:0000000140003017 db 45h, 8 dup(0)풀이 코드
nums = [0x49, 0x60, 0x67, 0x74, 0x63, 0x67, 0x42, 0x66, 0x80, 0x78, 0x69, 0x69, 0x7B, 0x99, 0x6D, 0x88, 0x68, 0x94, 0x9F, 0x8D, 0x4D, 0xA5, 0x9D, 0x45] for i in range(len(nums)) : tmp1 = nums[i] - (2 * i) tmp2 = tmp1 ^ i print(chr(tmp2), end = '')각 값에서 (2 * i)만큼 뺀다.
결과에 다시 i를 XOR 연산한다.
결과를 chr()로 문자로 변환해서 출력한다.
풀이
(16 * a1[i]) | (a1[i] >> 4) == byte_140003000[i]를 만족하는 a1을 찾아야 한다.
(a`1[i] << 4) | (a1[i] >> 4) == byte_140003000[i]16을 곱하는 것은 4비트 왼쪽 시프트하는 것과 같으므로 위와 같이 변경한다.
따라서 해당 프로그램에서 byte_140003000[i]의 앞뒤 위치를 바꾼 수가 a1[i]이 된다..data:0000000140003000 byte_140003000 db 24h, 27h, 13h, 2 dup(0C6h), 13h, 16h, 0E6h, 47h, 0F5h .data:0000000140003000 ; DATA XREF: sub_140001000+50↑o .data:000000014000300A db 26h, 96h, 47h, 0F5h, 46h, 27h, 13h, 2 dup(26h), 0C6h .data:0000000140003014 db 56h, 0F5h, 2 dup(0C3h), 0F5h, 2 dup(0E3h), 5 dup(0)따라서 다음의 연산을 다음의 byte_140003000 값과 진행하면 플래그 값을 찾을 수 있다.
풀이 코드
tmp = [0x24, 0x27, 0x13, 0xC6, 0xC6, 0x13, 0x16, 0xE6, 0x47, 0xF5, 0x26, 0x96, 0x47, 0xF5, 0x46, 0x27, 0x13, 0x26, 0x26, 0xC6, 0x56, 0xF5, 0xC3, 0xC3, 0xF5, 0xE3, 0xE3] for i in range(len(tmp)) : print(chr((tmp[i]<<4 | tmp[i]>>4) % (16 * 16)), end='')이 코드는 tmp 배열에 있는 각각의 16진수 값을 다음의 방식으로 처리한다.
tmp[i] << 4: 값을 왼쪽으로 4비트 시프트 (곱하기 16과 같음)
tmp[i] >> 4: 값을 오른쪽으로 4비트 시프트 (상위 4비트 추출)
|: 위의 두 값을 비트 OR 연산으로 합친다.
% 256: 결과를 256으로 나눈 나머지를 구해 0~255 범위로 제한한다.
풀이
함수 sub_140001000의 if절을 확인해보면a1[i + 1] + a1[i] == byte_140003000[i]를 만족해야 Correct가 출력됨을 확인 할 수 있다.
따라서 sub_140003000[i]의 값과 a1+i의 값을 역연산하여 플래그 값을 구해야한다.
풀이 코드j = 0 for j in range(33, 127) : i = 0 n = 0 res = [] res.append(j) for i in range(len(nums)) : res.append(nums[i] - res[i]) for n in range(len(res)) : print(chr(res[n]), end='') print() // 출력했을때 뭐가 많이 나오는데 .. 플래그 같은 것을 때려넣었다..
풀이
함수 sub_140001000의 if절을 확인해보면byte_140003020[a1[i]] == byte_140003000[i]를 만족해야함을 확인할 수 있다.
byte_140003020[j] == byte_140003000[i]먼저 이를 만족하는 j를 찾고 a1[i]의 값을 설정해주면 된다.
풀이 코드
nums = [0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16] nums2 = [0x00, 0x4D, 0x51, 0x50, 0xEF, 0xFB, 0xC3, 0xCF, 0x92, 0x45, 0x4D, 0xCF, 0xF5, 0x04, 0x40, 0x50, 0x43, 0x63] i = 0 j = 0 res = [0] * 0x12 for i in range(len(nums2)) : for j in range(len(nums)) : if nums2[i] == nums[j] : res[i] = j print(chr(j), end='') break각 값을 인덱스로 보정 후 XOR하여 복호화하였다.
풀이
특정 64비트 정수 배열(v10)에 저장된 암호화된 바이트들을,
HIBYTE(v5) = 66 (== 0x42, 즉 'B')를 이용해 XOR 연산으로 복호화한 뒤,
사용자가 입력한 플래그와 비교한다.v10[0] = 0x31397530273B230ELL; v10[1] = 0x292B2E1D27302336LL; v10[2] = 0x2B2A213623351D27LL; v10[3] = 0x31302336311D252CLL;입력된 값과 다음에 v10 배열들을 XOR 연산하는 것이다.
Layer7{stare_like_watching_stars}
정확하게는 Layer7{stare_like_watching_stars 가 계산된다...
풀이
check2에서 참이 반환되어야 하는 것을 알 수 있다.
입력[i]를 i % 8 + 1 비트 만큼 왼쪽으로 회전시킨 뒤, 5를 더한 값이 v3[i]와 같아야 한다.
따라서 이를 바탕으로 입력과 v3[i] 배열을 비교하여 조건에 따라 비트 연산한다.
그 후 최종값을 산출한다.Layer7{TWF5YmUgaXQncyB0aGUgbG92aW5nIGluIHlvdXIgZXllcw==}
풀이
문제 파일에 함수 main을 디컴파일 해보면
단순히 변수 flag의 값을 출력하는 프로그램인 것 같았다.
따라서 변수 flag에 들어있는 값을 확인해보았다.
그 결과로 다음과 같은 플래그 값을 알 수 있었다.
picoCTF{U51N6_Y0Ur_F1r57_F113_9bc52b6b}
풀이
문제 파일에 함수 main을 디컴파일 해보면
printf("The flag is : %s", flag);다음과 같은 출력 명령어를 주었으니, 변수 flag에 어떤 값이 들어있는지 확인해보았다.
확인해보니 다음과 같은 플래그 값이 들어있었다.picoCTF{F1r57_4rgum3n7_96f2195f}
풀이
문제 파일에 함수 main을 디컴파일 해보면
입력받은 s1의 값과 변수 aEae41779bdf799의 값을 비교했을 때,
똑같으면 참, 다르다면 거짓을 반환하는 조건문이다.
따라서 변수 aEae41779bdf799 안에 들어있는 문자열을 조사해 보았다.
그랬더니 다음과 같은 문자열이 입력되었을 때, '참'이 되는 것을 알 수 있었다.함수 main을 디컴파일 했을 때
printf("flag: FLAG{%S}", s1);다음과 같은 출력 명령문을 보았으니 플래그 형식은 FLAG{} 일 것이다.
따라서 제출할 플래그 값은 다음과 같다.
FLAG{eae41779bdf7990ade62d10c8f550dc1056f6a9f1b48a87d561f4ef49df17220}