Description

Category: Reversing/Binary

Source: Pragyan CTF 19

Points: 400

Author: Jisoon Park(js00n.park)

Description:

Open the Vault to get the treasure.

vault

Write-up

main() 함수를 보면 먼저 key를 입력받아서 몇가지 조건을 검사한다.

[...]

  v13 = 8;
  v14 = 229;
  v15 = 5;
  v16 = 25;
  v17 = 4;
  v18 = 83;
  v19 = 7;
  v20 = 135;
  v21 = 5;
  printf("Enter the key: ", argv, envp);
  __isoc99_scanf("%s", &s);
  if ( strlen(&s) > 0x1E )
    fail(0LL);
  v3 = getNum((__int64)"27644437104591489104652716127", 0, v13);
  if ( (unsigned int)mod(&s, v3) != v12 )
    fail(0LL);
  v9 = v13;
  v4 = getNum((__int64)"27644437104591489104652716127", v13, v15);
  if ( (unsigned int)mod(&s, v4) != v14 )
    fail(0LL);
  v10 = v15 + v9;
  v5 = getNum((__int64)"27644437104591489104652716127", v10, v17);
  if ( (unsigned int)mod(&s, v5) != v16 )
    fail(0LL);
  v11 = v17 + v10;
  v6 = getNum((__int64)"27644437104591489104652716127", v11, v19);
  if ( (unsigned int)mod(&s, v6) != v18 )
    fail(0LL);
  v8 = getNum((__int64)"27644437104591489104652716127", v19 + v11, v21);
  if ( (unsigned int)mod(&s, v8) != v20 )
    fail(0LL);
  printf("Enter password: ", v8);
  __isoc99_scanf("%s", &v23);
  func2((__int64)&v23, &s, "27644437104591489104652716127");

[...]

getNum(n, index, len) 함수는 문자열 형태로 주어진 십진수 숫자 n에서, index부터 len 만큼을 정수형으로 읽어오는 함수이다.

mod(n, d) 함수는 문자열 형태로 주어진 십진수 숫자를 d로 나눈 나머지를 돌려주는 함수이다.

즉, 5번의 if문은 입력 key에 대해, 아래와 같이 key % d = r 형태의 방정식 5개를 정의하고 있다.

key % 27644437 = 213
key % 10459 = 229
key % 1489 = 25
key % 1046527 = 83
key % 16127 = 135

이 5개의 방정식을 모두 만족시키는 key는 CRT(Chinese Remainder Theorem)을 이용하면 구할 수 있다.

여기에 python으로 구현된 CRT가 있어서 가져다 사용했다.

CRT를 풀면 3087629750608333480917556라는 key를 얻을 수 있다.

key를 입력하고 나면 이번엔 password를 입력받아서 func2() 함수로 들어간다.

int __fastcall func2(__int64 a1, char *a2, const char *a3)
{

[...]

  v12 = strcat(a2, a3);
  v3 = (unsigned __int64)&v12[strlen(v12)];
  *(_WORD *)v3 = 0x3038;
  *(_BYTE *)(v3 + 2) = 0;
  v7 = 0;
  v8 = 0;
  v10 = strlen(v12) >> 1;
  while ( v8 < strlen(v12) >> 1 )
  {
    if ( *(_BYTE *)(v7 + a1) != matrix[100 * (10 * (v12[v8] - 48) + v12[v8 + 1] - 48)
                                     - 48
                                     + 10 * (v12[v10] - 48)
                                     + v12[v10 + 1]] )
      fail(1LL);
    ++v7;
    v8 += 2;
    v10 += 2;
  }
  v9 = 0;
  v11 = strlen(v12) >> 1;
  while ( v9 < strlen(v12) >> 1 )
  {
    v4 = 10 * (v12[v9] - 48) + v12[v9 + 1] - 48;
    v5 = 10 * (v12[v11] - 48) + v12[v11 + 1] - 48;
    if ( *(_BYTE *)(v7 + a1) != matrix[100 * (v4 * v4 % 97) + v5 * v5 % 97] )
      fail(1LL);
    ++v7;
    v9 += 2;
    v11 += 2;
  }
  puts("Your Skills are really great. Flag is:");
  return printf("pctf{% raw  %}{%s}{% endraw %}\n", a1);
}

password로 입력받은 값이 matrix배열의 특정 위치의 값들과 동일한지 검사하는 루틴이다.

자세히 보면 v7을 1씩 증가시키면서 password의 앞에서부터 한 글자씩 비교하는 것을 볼 수 있는데, 이 비교 구문을 그냥 순서대로 쭉 모으면 password로 어떤 값을 넣어야 하는지 알 수 있다.

알고리즘들이 porting 하기에 비교적 간단해서 그냥 python으로 동일한 프로그램을 구현하여 실행한 결과, password를 얻을 수 있었다.

Flag : pctf{R3v3rS1Ng_#s_h311_L0t_Of_Fun}

'writeups > Reversing' 카테고리의 다른 글

Elementary  (0) 2019.11.26
ELF Crumble  (0) 2019.11.26
Feed_me  (0) 2019.11.25
Snakes over cheese  (0) 2019.11.25
Secrets  (0) 2019.11.25

Description

Category: Crypto

Source: Pragyan CTF 19

Points: 150

Author: Jisoon Park(js00n.park)

Description:

Rabin has received a text from someone special, but it's all in ciphertext and he is unable to make head or tail of it. He requested her for a little hint, and she sent him the encryption algorithm. He's still unable to decode the text. Not wanting to look dumb to her again, he needs your help in figuring out what she's written for him. So help him out.

ciphertext.txt
publickey.pem
encrypt.py

Write-up

먼저 encrypt.py 파일을 살펴보자.

[...]

p = getPrime(512)
q = nextPrime(p+1)
while p%4 != 3 or q%4 !=3:
    p = getPrime(512)
    q = nextPrime(p+1)

n = p*q
m = open('secret.txt').read()
m = bytes_to_long(m)

m = m**e
c = (m*m)%n

[...]

p와 q는 연속된 prime들이다. 실제로 찾아보면 (크기에 비해서는) 거의 차이가 없는 수이다. n의 square root부터 시작하면 brute-force로 금방 p와 q를 찾을 수 있을 것 같다.

그 다음으로는 d를 계산해서 modular exponentiation을 계산하면 plain text를 얻을 수 있을 텐데, 암호화 과정이 특이하다.
먼저 e 승을 해주는데, publickey.pem에서 확인해보면 e는 1이다. 그 후에 (m*m)%n을 계산하는데 RSA에서라면 e가 2인 셈이 된다. 그런데 조금 생각해보면 알겠지만, RSA에서는 e를 2로 사용하면 안된다. (d를 구할 수가 없다.)

어떻게 푸는 걸까. RSA public exponent 2검색을 했더니 Rabin Cryptosystem이라는 얘기가 나왔다. 문제 제목도 Rabin이고 알고리즘을 보아하니 (m*m)%n으로 암호화 하는 방식도 동일했다.

Rain Cryptosystem의 decryption algorithm에 따라 주어진 ciphertext를 복호화 하였더니 4개의 후보값이 나왔고, 그 중의 하나에서 flag를 찾을 수 있었다.

Flag : pctf{R4b1n_1s_th3_cut3st}

'writeups > Crypto' 카테고리의 다른 글

Easy Pisy  (0) 2019.11.26
Count me in  (0) 2019.11.26
Easy RSA  (0) 2019.11.25
Decode This  (0) 2019.11.25
:)  (0) 2019.11.25

Description

Category: Reversing/Binary

Source: Pragyan CTF 19

Points: 150

Author: Jisoon Park(js00n.park)

Description:

Can you cook the most delicious recipe?

nc 159.89.166.12 9800

challenge1

Write-up

main() 함수를 보면 임의로 생성된 세 숫자를 보여주고 '-' 또는 숫자로만 구성된 입력을 받는데, 길이제한 없이 "%s"로 받아서 bof 가 가능한 형태이다.

[...]

  char s[10]; // [rsp+32h] [rbp-6Eh]
  char nptr; // [rsp+3Ch] [rbp-64h]
  char v15; // [rsp+46h] [rbp-5Ah]

  [...]

  __isoc99_scanf("%s", s);
  for ( i = 0; i < strlen(s); ++i )
  {
    if ( (s[i] <= 0x2F || s[i] > 0x39) && s[i] != 45 )// '-' and numbers only
    {
      puts("Invalid input :( ");
      return 0;
    }
  }
  v9 = atoi(s);
  v10 = atoi(&nptr);
  v11 = atoi(&v15);
  if ( v6 == v9 + v10 )
  {
    if ( v7 == v10 + v11 )
    {
      if ( v8 == v11 + v9 )
      {
        stream = fopen("flag.txt", "r");
        if ( !stream )
        {
          fwrite("\nflag.txt doesn't exist.\n", 1uLL, 0x19uLL, stderr);
          exit(0);
        }
        fgets(&v16, 50, stream);
        printf("That's yummy.... Here is your gift:\n%s", &v16);

[...]

bof로 값을 덮어쓸 수 있는 변수는 s, nptr, v15 세 가지로, 각각 10 byte의 크기를 갖는다. (그 이후는 의미가 없거나 canary가 있다.)

값을 마음대로 줄 수 있는 세 변수에 대해 atoi()를 수행하고, 그 값을 이용한 if 조건문을 통과하면 간단히 flag를 준다.

if 조건문 세가지는 처음에 알려준 v6, v7, v8에 대한 것으로, 손으로도 쉽게 풀 수 있다.

한 가지 생각해야 하는건 '-'와 숫자만 입력받기 때문에, 앞을 0으로 채워서 길이를 맞춰줘야 한다.

간단히 방정식을 해결하고 payload를 구성하여 전송하는 exploit을 만들어서 flag를 얻었다.

Flag : pctf{p1zz4_t0pp3d_w1th_p1n34ppl3_s4uc3}

'writeups > Reversing' 카테고리의 다른 글

ELF Crumble  (0) 2019.11.26
Super Secure Vault  (0) 2019.11.26
Snakes over cheese  (0) 2019.11.25
Secrets  (0) 2019.11.25
Local News  (0) 2019.11.25

Description

Category: Crypto

Source: Pragyan CTF 19

Points: 150

Author: Jisoon Park(js00n.park)

Description:

Deeraj is experimenting with RSA. He is given the necessary RSA parameters. He realizes something is off, but doesn't know what. Can you help him figure it out?

parameters.txt

Write-up

RSA public key pair인 n, e와 암호문인 c가 주어진다.

그 외에는 주어진게 아무것도 없다. 그냥 n을 factorization 하라는 해야 할것 같다.

n을 생성하는 과정에 대한 힌트가 아무 것도 없으니, 그냥 RsaCtfTool을 이용해서 여러 방법을 다 시도해보자.

public key pair를 pem 형식으로 export 한 다음 RsaCtfTool에 던져주면 된다.

의외로 금방 찾아진다. wiener attack을 이용했을 때 factorization에 성공했다고 한다.

RsaCtfTool은 factorization에 성공하면 자동으로 private key를 계산해서 pem 파일까지 만들어준다.

만들어진 private key file을 로드한 다음 c를 byte array로 바꿔서 decryption하면 flag를 확인할 수 있다.

Flag : pctf{Sup3r_st4nd4rd_W31n3r_4tt4ck}

'writeups > Crypto' 카테고리의 다른 글

Count me in  (0) 2019.11.26
Help Rabin  (0) 2019.11.26
Decode This  (0) 2019.11.25
:)  (0) 2019.11.25
Revolutional Secure Angou  (0) 2019.11.25

+ Recent posts