본문 바로가기

CTF

[CTF] Codegate 2024 Write-up

보안 공부 시작하고 처음으로 코드게이트 CTF에 참가해봤습니다. 어렵긴 어렵지만 문제들이 재밌더라구요. 대회 끝난 이후에도 못 푼 문제들에 대해서 한 번 더 풀어볼 계획입니다.

 

리버싱 한 문제를 겨우 풀었는데, 나머지 문제들이 Rust랑 Basic으로 작성된 프로그램이어서 처음 분석하느라 애를 먹었네요. Rust 공부를 따로 하고 있는데, 조금 익숙해진 뒤에 다시 도전해보도록 하겠습니다.

 

Everlasting_Message

바이너리와 flag_enc 파일이 하나 주어집니다. flag_enc 파일의 크기가 약 200MB 정도 되네요.

 

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  _QWORD *v3; // rdx
  unsigned __int8 v5; // [rsp+1Fh] [rbp-F61h]
  int i; // [rsp+20h] [rbp-F60h]
  int j; // [rsp+24h] [rbp-F5Ch]
  int k; // [rsp+28h] [rbp-F58h]
  int m; // [rsp+2Ch] [rbp-F54h]
  int fd; // [rsp+30h] [rbp-F50h]
  int fd_2; // [rsp+34h] [rbp-F4Ch]
  unsigned __int64 index; // [rsp+38h] [rbp-F48h]
  size_t n; // [rsp+40h] [rbp-F40h]
  unsigned __int64 len; // [rsp+48h] [rbp-F38h]
  struct msgbuf msgp; // [rsp+50h] [rbp-F30h] BYREF
  char buf[1280]; // [rsp+70h] [rbp-F10h] BYREF
  char v17[2568]; // [rsp+570h] [rbp-A10h] BYREF
  unsigned __int64 v18; // [rsp+F78h] [rbp-8h]

  v18 = __readfsqword(0x28u);
  if ( a1 <= 2 )
    exit(-1);
  fd = open(a2[1], 0, a3);
  if ( fd < 0 )
    exit(-1);
  fd_2 = open(a2[2], 66, 0644LL);
  if ( fd_2 < 0 )
    exit(-1);
  msqid = msgget(0, 01666);
  if ( msqid < 0 )
    exit(-1);
  msqid_2 = msgget(0, 01666);
  if ( msqid_2 < 0 )
    exit(-1);
  for ( i = 0; i <= 3; ++i )
    pthread_create(&qword_90C0[i], 0LL, (void *(*)(void *))start_routine, &qword_9020[3 * i]);
  do
  {
    len = read(fd, buf, 0x500uLL);
    if ( len % 0xA )                            // 10의 배수로 패딩 작업
    {
      v5 = 10 - len % 0xA;
      for ( j = 0; j < v5; ++j )
        buf[len + j] = v5;
      len += v5;
    }
    index = 0LL;
    n = 0LL;
    while ( index < len )                       // len은 10의 배수
    {
      for ( k = 1; k <= 4; ++k )
      {
        msgp.mtype = k;
        v3 = *(_QWORD **)&buf[index + 8];
        msgp.mtext[0] = *(_QWORD **)&buf[index];
        msgp.mtext[1] = v3;
        if ( msgsnd(msqid, &msgp, 0x10uLL, 0) )
          perror("msgsnd-m");
      }
      for ( m = 1; m <= 4; ++m )
      {
        if ( msgrcv(msqid_2, &msgp, 0x10uLL, m, 0) < 0 )
          perror("msgrcv-m");
        memcpy(&v17[5 * m - 5 + n], msgp.mtext, 5uLL);
      }
      index += 10LL;
      n += 20LL;
    }
    write(fd_2, v17, n);
  }
  while ( len > 0x4FF );
  if ( msgctl(msqid, 0, 0LL) == -1 )
    exit(1);
  if ( msgctl(msqid_2, 0, 0LL) == -1 )
    exit(1);
  close(fd);
  close(fd_2);
  return 0LL;
}

 바이너리의 main 함수입니다.

스레드와 메세지 큐를 사용하는 것을 확인할 수 있습니다. flag 파일을 열어서 크기가 10의 배수가 아니면 패딩을 시켜줍니다.

 

msqid를 통해서 메세지 타입이랑 16바이트 크기의 데이터를 메세지 큐에 전송하고, msqid_2를 통해서 메세지 큐를 통해서 데이터를 전달받고 전달받은 데이터를 통해서 fd_2로 파일에 쓰기를 진행합니다. 

 

int __fastcall start_routine(__int64 (__fastcall **a1)(_QWORD))
{
  ssize_t v1; // rax
  __int64 v2; // rbx
  _QWORD *v4; // [rsp+10h] [rbp-70h]
  __int64 v5; // [rsp+20h] [rbp-60h]
  __int64 v6; // [rsp+28h] [rbp-58h]
  struct msgbuf msgp; // [rsp+30h] [rbp-50h] BYREF
  unsigned __int64 v8; // [rsp+68h] [rbp-18h]

  v8 = __readfsqword(0x28u);
  do
  {
    v1 = msgrcv(msqid, &msgp, 0x10uLL, *(int *)a1, 0);
    if ( v1 < 0 )
      break;
    v5 = ((__int64 (__fastcall **)(_QWORD **))a1)[1](msgp.mtext);
    v6 = a1[2](v5);
    v2 = v6 ^ (1LL << (rand() & 0x3F));
    v4 = (_QWORD *)(v2 ^ (1LL << (rand() & 0x3F)));
    msgp.mtype = *(int *)a1;
    msgp.mtext[0] = v4;
    LODWORD(v1) = msgsnd(msqid_2, &msgp, 0x10uLL, 0);
  }
  while ( !(_DWORD)v1 );
  return v1;
}

 전송한 메세지큐의 데이터들은 4개의 스레드에서 각각 처리 후 msqid_2를 통해서 데이터를 main 스레드로 전송합니다.

 매개변수에는 8바이트 크기의 메세지 타입, 8바이트 크기의 포인터변수 2개가 존재합니다.

 

*a1을 통해서 메세지 타입을 지정할 수 있고, a1[1]과 a1[2]를 통해서 함수를 호출합니다.

 

스레드마다 전달되는 매개변수가 다른데, 전체적인 흐름은 다음과 같습니다.

 

struct node{	// 매개변수의 타입을 정의
	long mtype;
	void *func_1;
	void *func_2;
};

1. a1[1] 함수는 전달받은 데이터 16바이트를 20bit씩 총 80bit(10바이트)의 데이터를 잘라(마스킹)줍니다.

2. a1[2] 함수는 마스킹한 데이터를 통해서 shift, xor 연산을 진행 후 값을 반환합니다.

3. 반환된 값에 rand() & 0x3F를 xor시켜서 bit를 오염시킵니다. 

4. 이후 값을 msqid_2를 통해서 메세지큐에 데이터를 전달합니다.

 

전달한 데이터는 메인 스레드에서 결과 파일에 저장하게 되는데, 이 때 5바이트만 저장하게 됩니다.

하지만 rand() & 0x3F는 5바이트 이상에도 데이터를 오염시킬 수 있기 때문에 이를 생각해보면 메인 스레드에서 파일에 저장하는 5바이트의 데이터는 오염된 비트의 갯수가 최소 0개, 최대 2개일 수 있습니다. 

 

처음에는 shift, xor 연산을 진행하는 함수에서 바로 복호화 하는 방법을 떠올리지 못해서 plain data를 브루트포싱하는 방법을 택하였습니다. plain data 2.5바이트당 0xfffff씩 브루트포싱하면 되기 때문에 plain data를 쉽게 구할 수 있지만, 이는 시간이 오래 걸리고, 더욱이 200메가나 되는 flag_enc 파일을 전부 복호화하는데 c언어로 구현해도 몇백시간이나 걸리는 것을 확인하고 포기하였습니다.(func_2 함수로 생성될 수 있는 데이터 테이블을 적용시켜도 오래 걸렸습니다.)

 

그래서 떠오른 방법이 flag_enc 5바이트로 plain data 2.5바이트를 구할 수 있는데, 오염된 bit 수가 최대 2개이기 때문에 flag_enc 5바이트가 테이블의 키값으로 존재하면 plain data를 바로 구할 수 있도록 구현하는 것이었습니다. 

40bit 중 오염된 비트가 최대 2개인 경우의 수는 최대 821개이기 때문에 5바이트의 데이터가 키값으로 존재하지 않으면 다른 오염된 경우의 수를 찾고 다시 키값이 존재하는 지 검사하는 식으로 시도하였습니다.

이렇게 하면 plain data를 0xFFFFF만큼 브루트포싱하는 것을 821번 브루트포싱 하면 되기 때문에 시간단축에 상당히 도움됩니다.   

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned long table[4][0xfffff];

unsigned char BYTE1(int a){
    return a >> 8;
};
unsigned char BYTE2(int a){
    return a >> 16;
};
unsigned short WORD1(int a){
    return a >> 16;
};
unsigned long sub_12E9(unsigned long a1);
unsigned long sub_264D(unsigned long a1);
unsigned long sub_3977(unsigned long a1);
unsigned long sub_4C0E(unsigned long a1);
int hasExactlyTwoOnes(unsigned long a);
void createTable();


int main(){
    FILE *file, *plain;
    unsigned long buffer=0, i, j;
    unsigned long data, result;
    unsigned long text[2] = { 0 };
    unsigned long long totalBytesRead = 0;
    unsigned long long fileSize = -1; // 파일 크기 (바이트), 초기값 -1로 설정
    size_t bytesRead;

    createTable();
    printf("Table create Done!\n");
}

unsigned long sub_12E9(unsigned long a1)
{
    long v1; // rax
    unsigned long v2; // rcx
    long v3; // rax
    unsigned long v4; // rcx
    unsigned long v5; // rdx
    long v6; // rax
    unsigned long v7; // rcx
    unsigned long v8; // rcx
    long v9; // rax
    unsigned long v10; // rdx
    long v11; // rax
    unsigned long v12; // rcx
    long v13; // rax
    long v14; // rcx

    v1 = (8
        * ((unsigned char)((a1 >> 18) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ BYTE1(a1) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 19))) & 8;
    v2 = (16
        * ((unsigned char)((a1 >> 18) ^ (a1 >> 13) ^ (a1 >> 10) ^ BYTE1(a1) ^ (a1 >> 6) ^ (a1 >> 5) ^ a1 ^ (a1 >> 4)) ^ (unsigned char)(a1 >> 19))) & 0x10 | v1 | (4 * ((unsigned char)((a1 >> 10) ^ BYTE1(a1) ^ (a1 >> 7) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 14))) & 4 | (2 * ((unsigned char)(BYTE2(a1) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ BYTE1(a1) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 4) ^ a1 ^ (a1 >> 2)) ^ (unsigned char)(a1 >> 17))) & 2 | (unsigned long)(((unsigned char)((a1 >> 18) ^ (a1 >> 17) ^ BYTE2(a1) ^ (a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ BYTE1(a1) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 2)) ^ (unsigned char)(a1 >> 19)) & 1);
    v3 = (((unsigned short)((a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 10) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 5) ^ (a1 >> 2) ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 17)) << 8) & 0x100;
    v4 = v3 | (unsigned char)(((unsigned char)((a1 >> 18) ^ (a1 >> 17) ^ BYTE2(a1) ^ (a1 >> 15) ^ (a1 >> 12) ^ (a1 >> 10) ^ (a1 >> 9) ^ BYTE1(a1) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 19)) << 7) | (((unsigned char)((a1 >> 17) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 11) ^ (a1 >> 9) ^ BYTE1(a1) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 18)) << 6) & 0x40 | (32 * ((unsigned char)((a1 >> 17) ^ BYTE2(a1) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ BYTE1(a1) ^ (a1 >> 6) ^ (a1 >> 3) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 18))) & 0x20 | v2;
    v5 = (((unsigned short)(WORD1(a1) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 9) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 19)) << 11) & 0x800 | (((unsigned short)((a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 11) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 17)) << 10) & 0x400 | (((unsigned short)((a1 >> 18) ^ (a1 >> 17) ^ (a1 >> 14) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 19)) << 9) & 0x200 | v4;
    v6 = (unsigned short)(((unsigned short)((a1 >> 17) ^ WORD1(a1) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2) ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 18)) << 15);
    v7 = v6 | (((unsigned short)((a1 >> 15) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 2) ^ (a1 >> 1)) ^ WORD1(a1)) << 14) & 0x4000 | (((unsigned short)((a1 >> 18) ^ WORD1(a1) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2) ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 19)) << 13) & 0x2000 | (((unsigned short)((a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 9) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 2)) ^ (unsigned short)(a1 >> 17)) << 12) & 0x1000 | v5;
    v8 = (((unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 19)) << 19) & 0x80000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 19)) << 18) & 0x40000 | (((unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 16)) << 17) & 0x20000 | (((unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 15)) << 16) & 0x10000 | v7;
    v9 = (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 18)) << 23) & 0x800000;
    v10 = (((unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 14)) << 24) & 0x1000000 | v9 | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 22) & 0x400000 | (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 21) & 0x200000 | (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 20) & 0x100000 | v8;
    v11 = (((unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 10)) << 29) & 0x20000000;
    v12 = v11 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 19)) << 28) & 0x10000000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 27) & 0x8000000 | (((unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 16)) << 26) & 0x4000000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 25) & 0x2000000 | v10;
    v13 = (((a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 4) ^ (a1 >> 2) ^ (a1 >> 18)) << 35) & 0x800000000;
    v14 = v13 | (((a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 10) ^ (a1 >> 8) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 1) ^ (a1 >> 16)) << 34) & 0x400000000 | (((a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1) ^ (a1 >> 18)) << 33) & 0x200000000 | (((a1 >> 17) ^ (a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 12) ^ (a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 3) ^ a1 ^ (a1 >> 1) ^ (a1 >> 18)) << 32) & 0x100000000 | (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 18)) << 31) | (((unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 18)) << 30) & 0x40000000 | v12;
    return (((a1 >> 17) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 1) ^ (a1 >> 19)) << 38) & 0x4000000000 | (((a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 2) ^ (a1 >> 17)) << 37) & 0x2000000000 | (((a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 10) ^ (a1 >> 3) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1) ^ (a1 >> 17)) << 36) & 0x1000000000 | v14 | (((a1 >> 18) ^ (a1 >> 15) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 19)) << 39) & 0x8000000000;
};

unsigned long sub_264D(unsigned long a1)
{
    long v1; // rax
    unsigned long v2; // rdx
    unsigned long v3; // rcx
    long v4; // rax
    unsigned long v5; // rdx
    long v6; // rax
    unsigned long v7; // rdx
    unsigned long v8; // rcx
    unsigned long v9; // rdx
    unsigned long v10; // rcx
    unsigned long v11; // rdx
    long v12; // rdx

    v1 = (16
        * ((unsigned char)((a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 9) ^ BYTE1(a1) ^ (a1 >> 5) ^ (a1 >> 4) ^ a1 ^ (a1 >> 3)) ^ (unsigned char)(a1 >> 17))) & 0x10;
    v2 = v1 | (8
            * ((unsigned char)(BYTE2(a1) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 18))) & 8 | (4 * ((unsigned char)(BYTE2(a1) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 19))) & 4 | (2 * ((unsigned char)(BYTE2(a1) ^ (a1 >> 15) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ BYTE1(a1) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4)) ^ (unsigned char)(a1 >> 18))) & 2 | (unsigned long)(((unsigned char)((a1 >> 18) ^ BYTE2(a1) ^ (a1 >> 13) ^ (a1 >> 12) ^ BYTE1(a1) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 19)) & 1);
    v3 = (unsigned char)(((unsigned char)((a1 >> 18) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ BYTE1(a1) ^ (a1 >> 5) ^ a1 ^ (a1 >> 2)) ^ (unsigned char)(a1 >> 19)) << 7) | (((unsigned char)((a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 10) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2)) ^ (unsigned char)(a1 >> 19)) << 6) & 0x40 | (32 * ((unsigned char)((a1 >> 17) ^ (a1 >> 12) ^ (a1 >> 10) ^ (a1 >> 9) ^ BYTE1(a1) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 19))) & 0x20 | v2;
    v4 = (((unsigned short)((a1 >> 17) ^ WORD1(a1) ^ (a1 >> 13) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 6) ^ (a1 >> 5) ^ a1 ^ (a1 >> 4)) ^ (unsigned short)(a1 >> 18)) << 12) & 0x1000;
    v5 = v4 | (((unsigned short)((a1 >> 18) ^ (a1 >> 17) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 7) ^ (a1 >> 5)) ^ (unsigned short)(a1 >> 19)) << 11) & 0x800 | (((unsigned short)((a1 >> 17) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 19)) << 10) & 0x400 | (((unsigned short)((a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 5) ^ (a1 >> 4) ^ a1 ^ (a1 >> 3)) ^ (unsigned short)(a1 >> 19)) << 9) & 0x200 | (((unsigned short)((a1 >> 17) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 10) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 5) ^ (a1 >> 4) ^ a1 ^ (a1 >> 2)) ^ (unsigned short)(a1 >> 18)) << 8) & 0x100 | v3;
    v6 = (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 19)) << 17) & 0x20000;
    v7 = v6 | (((unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 18)) << 16) & 0x10000 | (unsigned short)(((unsigned short)((a1 >> 13) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 5) ^ (a1 >> 2) ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 17)) << 15) | (((unsigned short)((a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 9) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 2) ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 19)) << 14) & 0x4000 | (((unsigned short)(WORD1(a1) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 6) ^ (a1 >> 4)) ^ (unsigned short)(a1 >> 18)) << 13) & 0x2000 | v5;
    v8 = (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 19)) << 20) & 0x100000 | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 19) & 0x80000 | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 19)) << 18) & 0x40000 | v7;
    v9 = (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 24) & 0x1000000 | (((unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 23) & 0x800000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 22) & 0x400000 | (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 21) & 0x200000 | v8;
    v10 = (((unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 13)) << 28) & 0x10000000 | (((unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 16)) << 27) & 0x8000000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 26) & 0x4000000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 18)) << 25) & 0x2000000 | v9;
    v11 = (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 31) | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 30) & 0x40000000 | (((unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 16)) << 29) & 0x20000000 | v10;
    v12 = (((a1 >> 17) ^ (a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 11) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 1) ^ (a1 >> 19)) << 36) & 0x1000000000 | (((a1 >> 15) ^ (a1 >> 12) ^ (a1 >> 9) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 1) ^ (a1 >> 18)) << 35) & 0x800000000 | (((a1 >> 18) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 11) ^ (a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ a1 ^ (a1 >> 1) ^ (a1 >> 19)) << 34) & 0x400000000 | (((a1 >> 18) ^ (a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 2) ^ (a1 >> 19)) << 33) & 0x200000000 | (((a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 10) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 2) ^ (a1 >> 16)) << 32) & 0x100000000 | v11;
    return (((a1 >> 16) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 1) ^ (a1 >> 17)) << 38) & 0x4000000000 | (((a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 9) ^ (a1 >> 8) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 1) ^ (a1 >> 19)) << 37) & 0x2000000000 | v12 | (((a1 >> 17) ^ (a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 11) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1) ^ (a1 >> 19)) << 39) & 0x8000000000;
}

unsigned long sub_3977(unsigned long a1)
{
    unsigned long v1; // rcx
    unsigned long v2; // rcx
    unsigned long v3; // rcx
    unsigned long v4; // rdx
    unsigned long v5; // rcx
    unsigned long v6; // rcx
    unsigned long v7; // rdx
    unsigned long v8; // rdx
    long v9; // rdx

    v1 = (16
        * ((unsigned char)((a1 >> 17) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 10) ^ BYTE1(a1) ^ (a1 >> 6) ^ a1 ^ (a1 >> 3)) ^ (unsigned char)(a1 >> 18))) & 0x10 | (8 * ((unsigned char)((a1 >> 13) ^ (a1 >> 11) ^ (a1 >> 4)) ^ BYTE2(a1))) & 8 | (4 * ((unsigned char)((a1 >> 18) ^ BYTE2(a1) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 3) ^ a1 ^ (a1 >> 2)) ^ (unsigned char)(a1 >> 19))) & 4 | (2 * ((unsigned char)((a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 9) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2)) ^ (unsigned char)(a1 >> 19))) & 2 | (unsigned long)(((unsigned char)((a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 5) ^ (a1 >> 3) ^ a1 ^ (a1 >> 2)) ^ BYTE2(a1)) & 1);
    v2 = (((unsigned short)(WORD1(a1) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 3) ^ a1 ^ (a1 >> 2)) ^ (unsigned short)(a1 >> 17)) << 8) & 0x100 | (unsigned char)(((unsigned char)((a1 >> 14) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 4)) ^ (unsigned char)(a1 >> 17)) << 7) | (((unsigned char)((a1 >> 17) ^ BYTE2(a1) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 6) ^ (a1 >> 2)) ^ (unsigned char)(a1 >> 18)) << 6) & 0x40 | (32 * ((unsigned char)((a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2) ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 19))) & 0x20 | v1;
    v3 = (((unsigned short)((a1 >> 18) ^ WORD1(a1) ^ (a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 3)) ^ (unsigned short)(a1 >> 19)) << 12) & 0x1000 | (((unsigned short)((a1 >> 17) ^ (a1 >> 13) ^ (a1 >> 9) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 3)) ^ (unsigned short)(a1 >> 19)) << 11) & 0x800 | (((unsigned short)((a1 >> 17) ^ WORD1(a1) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ a1 ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 18)) << 10) & 0x400 | (((unsigned short)((a1 >> 11) ^ (a1 >> 10) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 6) ^ a1 ^ (a1 >> 5)) ^ (unsigned short)(a1 >> 15)) << 9) & 0x200 | v2;
    v4 = (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 17) & 0x20000 | (((unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 14)) << 16) & 0x10000 | (unsigned short)(((unsigned short)((a1 >> 17) ^ WORD1(a1) ^ (a1 >> 15) ^ (a1 >> 11) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 4) ^ (a1 >> 2)) ^ (unsigned short)(a1 >> 19)) << 15) | (((unsigned short)((a1 >> 18) ^ (a1 >> 13) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2)) ^ (unsigned short)(a1 >> 19)) << 14) & 0x4000 | (((unsigned short)((a1 >> 12) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 6) ^ (a1 >> 4) ^ a1 ^ (a1 >> 2)) ^ (unsigned short)(a1 >> 18)) << 13) & 0x2000 | v3;
    v5 = (((unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 17)) << 21) & 0x200000 | (((unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 16)) << 20) & 0x100000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 19) & 0x80000 | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 19)) << 18) & 0x40000 | v4;
    v6 = (((unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 16)) << 24) & 0x1000000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 23) & 0x800000 | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 22) & 0x400000 | v5;
    v7 = (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 17)) << 28) & 0x10000000 | (((unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 17)) << 27) & 0x8000000 | (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 26) & 0x4000000 | (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 18)) << 25) & 0x2000000 | v6;
    v8 = (((unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 31) | (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 30) & 0x40000000 | (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 29) & 0x20000000 | v7;
    v9 = (((a1 >> 13) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 2) ^ (a1 >> 19)) << 36) & 0x1000000000LL | (((a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 9) ^ (a1 >> 8) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 19)) << 35) & 0x800000000LL | (((a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ a1 ^ (a1 >> 2) ^ (a1 >> 19)) << 34) & 0x400000000LL | (((a1 >> 18) ^ (a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 4) ^ a1 ^ (a1 >> 1) ^ (a1 >> 19)) << 33) & 0x200000000LL | (((a1 >> 18) ^ (a1 >> 17) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 8) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2) ^ (a1 >> 19)) << 32) & 0x100000000LL | v8;
    return (((a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 7) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 2) ^ (a1 >> 18)) << 38) & 0x4000000000LL | (((a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 2) ^ (a1 >> 1) ^ (a1 >> 18)) << 37) & 0x2000000000LL | v9 | (((a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2) ^ (a1 >> 1) ^ (a1 >> 16)) << 39) & 0x8000000000LL;
}

unsigned long sub_4C0E(unsigned long a1)
{
    unsigned long v1; // rcx
    unsigned long v2; // rcx
    unsigned long v3; // rcx
    unsigned long v4; // rcx
    long v5; // rax
    unsigned long v6; // rcx
    unsigned long v7; // rcx
    unsigned long v8; // rdx
    unsigned long v9; // rdx
    long v10; // rcx
    long v11; // rcx

    v1 = (8
        * ((unsigned char)((a1 >> 13) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 18))) & 8 | (4 * ((unsigned char)((a1 >> 11) ^ BYTE1(a1) ^ (a1 >> 5) ^ a1 ^ (a1 >> 3)) ^ (unsigned char)(a1 >> 18))) & 4 | (2 * ((unsigned char)(BYTE2(a1) ^ (a1 >> 15) ^ (a1 >> 12) ^ (a1 >> 10) ^ (a1 >> 9) ^ BYTE1(a1) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 3) ^ a1 ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 19))) & 2 | (unsigned long)(((unsigned char)((a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ BYTE1(a1) ^ (a1 >> 7)) ^ BYTE2(a1)) & 1);
    v2 = (unsigned char)(((unsigned char)((a1 >> 18) ^ BYTE2(a1) ^ (a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 10) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 3) ^ a1 ^ (a1 >> 2)) ^ (unsigned char)(a1 >> 19)) << 7) | (((unsigned char)((a1 >> 12) ^ BYTE1(a1) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 2) ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 14)) << 6) & 0x40 | (32 * ((unsigned char)((a1 >> 15) ^ (a1 >> 12) ^ (a1 >> 10) ^ (a1 >> 9) ^ BYTE1(a1) ^ (a1 >> 5) ^ (a1 >> 4)) ^ (unsigned char)(a1 >> 18))) & 0x20 | (16 * ((unsigned char)(BYTE2(a1) ^ (a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1)) ^ (unsigned char)(a1 >> 19))) & 0x10 | v1;
    v3 = (((unsigned short)(WORD1(a1) ^ (a1 >> 15) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 6) ^ (a1 >> 5) ^ a1 ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 18)) << 11) & 0x800 | (((unsigned short)(WORD1(a1) ^ (a1 >> 14) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 2) ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 19)) << 10) & 0x400 | (((unsigned short)((a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 7) ^ a1 ^ (a1 >> 6)) ^ (unsigned short)(a1 >> 13)) << 9) & 0x200 | (((unsigned short)((a1 >> 18) ^ (a1 >> 17) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 9) ^ (a1 >> 5) ^ (a1 >> 3) ^ a1 ^ (a1 >> 2)) ^ (unsigned short)(a1 >> 19)) << 8) & 0x100 | v2;
    v4 = (unsigned short)(((unsigned short)((a1 >> 14) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1)) ^ WORD1(a1)) << 15) | (((unsigned short)((a1 >> 18) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 5) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 2) ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 19)) << 14) & 0x4000 | (((unsigned short)((a1 >> 13) ^ (a1 >> 11) ^ (a1 >> 10) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1)) ^ (unsigned short)(a1 >> 17)) << 13) & 0x2000 | (((unsigned short)((a1 >> 11) ^ (a1 >> 10) ^ ((unsigned int)a1 >> 8) ^ (a1 >> 4) ^ a1 ^ (a1 >> 2)) ^ WORD1(a1)) << 12) & 0x1000 | v3;
    v5 = (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 19)) << 19) & 0x80000;
    v6 = v5 | (((unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 15)) << 18) & 0x40000 | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 19)) << 17) & 0x20000 | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 19)) << 16) & 0x10000 | v4;
    v7 = (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 22) & 0x400000 | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 19)) << 21) & 0x200000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 18)) << 20) & 0x100000 | v6;
    v8 = (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 25) & 0x2000000 | (((unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 19)) << 24) & 0x1000000 | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 2) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 23) & 0x800000 | v7;
    v9 = (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 2) ^ (unsigned int)(a1 >> 18)) << 28) & 0x10000000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 27) & 0x8000000 | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 15) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 18)) << 26) & 0x4000000 | v8;
    v10 = (((a1 >> 17) ^ (a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 10) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1) ^ (a1 >> 18)) << 32) & 0x100000000LL | (((unsigned int)(a1 >> 18) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 14) ^ (unsigned int)(a1 >> 13) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 6) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 3) ^ (unsigned int)a1 ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 19)) << 31) | (((unsigned int)(a1 >> 17) ^ (unsigned int)(a1 >> 16) ^ (unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 11) ^ (unsigned int)(a1 >> 9) ^ (unsigned int)(a1 >> 8) ^ (unsigned int)(a1 >> 7) ^ (unsigned int)(a1 >> 4) ^ (unsigned int)(a1 >> 19)) << 30) & 0x40000000 | (((unsigned int)(a1 >> 12) ^ (unsigned int)(a1 >> 10) ^ (unsigned int)(a1 >> 5) ^ (unsigned int)(a1 >> 1) ^ (unsigned int)(a1 >> 17)) << 29) & 0x20000000 | v9;
    v11 = (((a1 >> 15) ^ (a1 >> 14) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ a1 ^ (a1 >> 3) ^ (a1 >> 17)) << 37) & 0x2000000000LL | (((a1 >> 15) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1) ^ (a1 >> 17)) << 36) & 0x1000000000LL | (((a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 8) ^ (a1 >> 5) ^ (a1 >> 3) ^ (a1 >> 2) ^ (a1 >> 1) ^ (a1 >> 16)) << 35) & 0x800000000LL | (((a1 >> 17) ^ (a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 8) ^ (a1 >> 4) ^ (a1 >> 2) ^ (a1 >> 1) ^ (a1 >> 18)) << 34) & 0x400000000LL | (((a1 >> 13) ^ (a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 9) ^ (a1 >> 6) ^ (a1 >> 5) ^ (a1 >> 4) ^ a1 ^ (a1 >> 3) ^ (a1 >> 16)) << 33) & 0x200000000LL | v10;
    return (((a1 >> 18) ^ (a1 >> 16) ^ (a1 >> 15) ^ (a1 >> 11) ^ (a1 >> 10) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 3) ^ (a1 >> 2) ^ a1 ^ (a1 >> 1) ^ (a1 >> 19)) << 38) & 0x4000000000LL | v11 | (((a1 >> 12) ^ (a1 >> 11) ^ (a1 >> 9) ^ (a1 >> 8) ^ (a1 >> 7) ^ (a1 >> 6) ^ (a1 >> 4) ^ (a1 >> 3) ^ a1 ^ (a1 >> 2) ^ (a1 >> 18)) << 39) & 0x8000000000LL;
};

int hasExactlyTwoOnes(unsigned long a) {
    int count = 0;

    // 비트 연산을 통해 1의 개수를 셈
    while (a != 0) {
        if (a & 1) {
            count++;
        }
        a >>= 1; // 오른쪽으로 한 비트 이동
    }

    // 1의 개수가 2개인지 확인
    return count <= 2;
}

void createTable(){
    FILE *file;
    file = fopen("table", "w");
    int i, j;
    unsigned long(*func)(unsigned long);
    for(i = 0; i < 4; i++){
        for(j = 0; j <= 0xfffff; j++){
            if(i == 0){
                func = sub_12E9;
            }
            else if(i == 1){
                func = sub_264D;
            }
            else if(i == 2){
                func = sub_3977;
            }
            else if(i == 3){
                func = sub_4C0E;
            }
            table[i][j] = func(j);
            fprintf(file, "%d %d %ld\n", i, j, table[i][j]);
        }
        fprintf(file, "----------\n");
    }
}

위 코드는 테이블을 생성하는 코드인데, gdb script로 함수 결과를 알 수 있지만 귀찮기 때문에 함수 코드를 복붙해왔습니다.

 

from tqdm import tqdm
def gen_numbers():
    result = [0]
    
    for i in range(0, 40):
        result.append(1 << i)
    for j in range(1, 40):
        for i in range(0, j):
            result.append((1 << j) | (1 << i))
    return result

numbers = gen_numbers()
    
with open('table', 'r') as f:
    buf = f.read().split('----------')[:-1]
table = [{} for _ in range(4)]

for data in buf:
    for line in data.split('\n')[:-1]:
        arr = list(map(int, line.split()))
        try:
            table[arr[0]][arr[2]] = arr[1]
        except:
            pass

with open('flag_enc', 'rb') as f:
    buf = f.read()
    
    
content = b''
for i in tqdm(range(0, len(buf), 20)):
    write_data = 0
    for j in range(0, 20, 5):
        data = int.from_bytes(buf[i+j:i+j+5], 'little')
        for number in numbers:
            tmp = data ^ number
            try:
                result = table[j // 4][tmp]
                write_data |= result << (20 * (j // 4))
                break
            except:
                pass
    content += write_data.to_bytes(10, byteorder='little')
        
with open('movie.mp4', 'wb') as f:
    f.write(content)
print('Done')

복호화하는 코드는 위의 파이썬 코드입니다.

 

실행하면 위 사진처럼 진행도를 표현해주는데, 저는 복호화하는데 대략 40분 걸린 것 같습니다.

 

복호화가 끝나면 mp4 파일이 생성되는데, 거기에 플래그가 있는 것을 확인할 수 있습니다.

 

후기

처음 참여해 본 코드게이트 CTF... 많이 어렵네요. 지난번 .HACK Invitational에서는 한 문제도 못 풀었었는데 그래도 이번 코게때는 한 문제는 해결했네요 ..ㅎㅎ..

드림핵에서 c로 작성된 ELF, EXE 파일만 디버깅 했었는데 앞으로 rust나 Basic, 기타 다른 프로그램 분석을 좀 더 많이 해봐야할 것 같습니다.(+ 수학공부도..)

'CTF' 카테고리의 다른 글

[CTF] CCE 2024 Qual Write-up  (0) 2024.08.13
[CTF] LINE CTF 2023  (0) 2023.03.28
[CTF] wolvCTF  (0) 2023.03.20