크랙미 풀이 (12-07 ~ 12-16)

_2·2024년 12월 13일

Crackme

목록 보기
1/12

1. Tut's LSDtrip crackme!

AuthorLanguageUploadPlatformDifficultyQualityArch
TutC/C++2:54 PM 11/20/2024Windows2.64.5x86
The goal is to get the right password without patching. This way, you will ultimately prove that you are not tripping on LSD!
void __noreturn sub_401000()
{
  int i; // [esp+0h] [ebp-Ch]
  int v1; // [esp+4h] [ebp-8h]
  char *Buffer; // [esp+8h] [ebp-4h]

  printf("\n     \"LSDtrip\"\" crackme by Alon Alush, alonalush5@gmail.com       \n\n PASSWORD >>> ");
  Buffer = malloc(20u);
  fgets(Buffer, 20, iob[0]._ptr);
  v1 = 0;
  for ( i = 0; Buffer[i]; ++i )
    v1 += (i + 1) * Buffer[i];
  if ( strlen(Buffer) == 5 && v1 == 945 )
    printf("\n [+] Good job! You sober! \n");
  else
    printf("\nWrong! I think you're on LSD?");
  getch();
  exit(0);
}

point: 입력 끝에 LF (\n)가 들어감.

(input[0]*1) + (input[1]*2) + (input[2]*3) + (input[3]*4) + 50 = 945 가 되야 함.
브루트포스로 풀림.

2. tyller's Hard work bro

AuthorLanguageUploadPlatformDifficultyQualityArch
tyllerC/C++4:54 PM 12/07/2024Windows3.73.7x86
this is very hard uses and encryption and other stuff if you really do it write to chat please, my pleasure if you crack it 
int __cdecl main(int argc, const char **argv, const char **envp)
{
  __main();
  check_for_licenses();
  admin_check();
  authentication();
  return 0;
}

__main: init 코드
check_for_licenses: license 파일 읽는 코드
admin_check: 2단계
authentication: 1단계

const char *__cdecl get_character_mapping(char a1)
{
  const char *result; // eax

  switch ( a1 )
  {
    case ')':
      result = "999";
      break;
    case ':':
      result = "666";
      break;
    case '_':
      result = "000";
      break;
    case 'a':
      result = "854";
      break;
    case 'b':
      result = "789";
      break;
    case 'c':
      result = "348";
      break;
    case 'd':
      result = "548";
      break;
    case 'e':
      result = "157";
      break;
    case 'f':
      result = "784";
      break;
    case 'g':
      result = "789";
      break;
    case 'h':
      result = "435";
      break;
    case 'i':
      result = "197";
      break;
    case 'j':
      result = "257";
      break;
    case 'k':
      result = "394";
      break;
    case 'l':
      result = "428";
      break;
    case 'm':
      result = "981";
      break;
    case 'n':
      result = "214";
      break;
    case 'o':
      result = "764";
      break;
    case 'p':
      result = "367";
      break;
    case 'q':
      result = "698";
      break;
    case 'r':
      result = "101";
      break;
    case 's':
      result = "768";
      break;
    case 't':
      result = "648";
      break;
    case 'u':
      result = "286";
      break;
    case 'v':
      result = "784";
      break;
    case 'w':
      result = "168";
      break;
    case 'x':
      result = "798";
      break;
    case 'y':
      result = "314";
      break;
    case 'z':
      result = "972";
      break;
    default:
      result = "???";
      break;
  }
  return result;
}

char *__cdecl technical_thinks(const char *Str, char *a2)
{
  char v3[2]; // [esp+18h] [ebp-C20h] BYREF
  char v4[2]; // [esp+1Ah] [ebp-C1Eh] BYREF
  char v5[1024]; // [esp+1Ch] [ebp-C1Ch] BYREF
  char v6[1024]; // [esp+41Ch] [ebp-81Ch] BYREF
  char Destination[1024]; // [esp+81Ch] [ebp-41Ch] BYREF
  int v8; // [esp+C1Ch] [ebp-1Ch]
  char *Source; // [esp+C20h] [ebp-18h]
  size_t k; // [esp+C24h] [ebp-14h]
  size_t j; // [esp+C28h] [ebp-10h]
  size_t i; // [esp+C2Ch] [ebp-Ch]

  memset(Destination, 0, sizeof(Destination));
  memset(v6, 0, sizeof(v6));
  memset(v5, 0, sizeof(v5));
  for ( i = 0; strlen(Str) > i; ++i )
  {
    Source = get_character_mapping(Str[i]);
    strcat(Destination, Source);
  }
  for ( j = 0; strlen(Destination) > j; ++j )
  {
    if ( Destination[j] > 0x2F && Destination[j] <= 57 )
    {
      v4[0] = (Destination[j] - 48) / 2 + 48;
      v4[1] = 0;
      strcat(v6, v4);
    }
  }
  for ( k = 0; strlen(v6) > k; ++k )
  {
    v8 = v6[k] - 48;
    if ( (v8 & 1) == 0 )
    {
      v3[0] = v8 / 2 + 48;
      v3[1] = 0;
      strcat(v5, v3);
    }
  }
  return strcpy(a2, v5);
}

char *global_main_for_other(void)
{
  char Buffer[264]; // [esp+10h] [ebp-108h] BYREF

  printf("Password to get the licence: ");
  fgets(Buffer, 256, __iob[0]._ptr);
  Buffer[strcspn(Buffer, "\n")] = 0;
  if ( Buffer[0] )
  {
    technical_thinks(Buffer, global_main_for_other(void)::final_hash);
    return global_main_for_other(void)::final_hash;
  }
  else
  {
    puts("Error: Input is empty!");
    return 0;
  }
}

int authentication(void)
{
  const char *Str1; // [esp+18h] [ebp-10h]

  Str1 = global_main_for_other();
  if ( Str1 )
  {
    if ( !strcmp(Str1, "110112121") )
    {
      puts("Authentication Successful");
      puts("We will generate license to prove that you did it ...");
      ready();
      return 0;
    }
    else
    {
      puts("Authentication Failed");
      return 1;
    }
  }
  else
  {
    puts("Error, invalid input");
    return 1;
  }
}

point: technical_thinks 내의 마지막 과정에서 v8[k]이 짝수인 경우만 쓰이기 때문에 여러 답이 나올 수 있음.

technical_thinks 연산 이후 비밀번호와 "110112121"를 비교함.
길이 1~3으로 잘랐을 때 세 경우 모두 구할 수 없는지를 조건으로 두고 백트래킹으로 풀림.

2단계는 "2101000010002120001012200021122021000112"와 비교함.
같은 코드로 풀림.

3. thed0ublec's CrazyCrackMe

AuthorLanguageUploadPlatformDifficultyQualityArch
thed0ublec.NET2:03 PM 12/09/2024Windows3.74.3x86-64
CrazyCrackMe! this is so crazy!! who can try?
private static bool lIllIlIIlIlIIlIl(string lIlIlIIlIlIIlIlI)
		{
        	// check 1: null/empty check
			bool flag = string.IsNullOrEmpty(lIlIlIIlIlIIlIlI);
			bool result;
			if (flag)
			{
				result = false;
			}
			else
			{
            	// check 2: length check
                // return length >= 8 && length <= 16;
				bool flag2 = !lIIlIIIlIIIlIIIlIlIIIlIIIlIIIIlII.lIllIIlIlIIlIlIl.lIlIIlIlIlIlIlIl(lIlIlIIlIlIIlIlI.Length);
				if (flag2)
				{
					result = false;
				}
				else
				{
                	// check 3: data check
                    /*
                    int num = 0;
					foreach (char c in data)
					{
						num = (num << 3 ^ (int)(c * '\u0011'));
					}
					return (num & 65535) == 23130;
            */
					bool flag3 = !lIIlIIIlIIIlIIIlIlIIIlIIIlIIIIlII.lIllIlIIlIlIllIl(lIlIlIIlIlIIlIlI);
					if (flag3)
					{
						result = false;
					}
					else
					{
                    	// check 4: data check 2
                        /*
                        // decrypt to get "CrazyCrackMe"
                        string text = lIIlIIIlIIIlIIIlIlIIIlIIIlIIIIlII.lIlIIlIIlIIlIllI(lIIlIIlIlIllIllI);
						// check if data contain "CrazyCrackMe".reverse()
                        return text.Contains(lIIlIIIlIIIlIIIlIlIIIlIIIlIIIIlII.lIlIIlIlIlIlIIlIl("lIllllIIlIIIllIllIIllllIlIIIIlIllIIIIllIlIllllIIlIIIllIllIIllllIlIIlllIIlIIlIlIIlIllIIlIlIIllIlI"));
            */
						bool flag4 = !lIIlIIIlIIIlIIIlIlIIIlIIIlIIIIlII.lIIlIIlIIlIIlIllI(lIlIlIIlIlIIlIlI);
						result = !flag4;
					}
				}
			}
			return result;
		}
        
// main
{
            // ...
		 	string lIlIlIIlIlIIlIlI = Console.ReadLine().Trim();
			bool flag2 = lIIlIIIlIIIlIIIlIlIIIlIIIlIIIIlII.lIllIlIIlIlIIlIl(lIlIlIIlIlIIlIlI);
			if (flag2)
			{
				Console.Clear();
				Console.ForegroundColor = ConsoleColor.Green;
				Console.WriteLine(lIIlIIIlIIIlIIIlIlIIIlIIIlIIIIlII.lIlIIlIlIlIlIIlIl(lIllIllIllIIlIll3));
				Console.WriteLine("\r\n" + lIIlIIIlIIIlIIIlIlIIIlIIIlIIIIlII.lIlIIlIlIlIlIIlIl(lIllIllIllIIlIll4));
				Console.ReadLine();
			}
			else
			{
				Console.ForegroundColor = ConsoleColor.Red;
				Console.WriteLine(lIIlIIIlIIIlIIIlIlIIIlIIIlIIIIlII.lIlIIlIlIlIlIIlIl(lIllIllIllIIlIll5));
				Console.ReadLine();
			}
}

point: 마지막 조건으로 인해 브루트포스가 가능해짐.

모든 문자열을 복호화해서 사용하고 변수명이 난독화 되어있음.
"CrazyCrackMe"[::-1] 뒤에 1~4개의 문자가 있는 문자열을 만들면 됨.
브루트포스로 풀림.

4. SUSPEKT's crypted string crackme

AuthorLanguageUploadPlatformDifficultyQualityArch
SUSPEKTC/C++8:29 PM 12/09/2024Windows2.04.0x86-64
selfcoded string encryptor, the goal = get password. you can do anything to get password.

비밀번호 복호화 이후 입력 받고 비교함.

5. hybridkenrel's yum :P

AuthorLanguageUploadPlatformDifficultyQualityArch
hybridkenrelC/C++2:56 PM 12/07/2024Unix/linux etc.2.04.0x86-64
You must get the output "Success!"

폴더 내의 libyum.so를 읽어서 특정 부분의 문자열을 비밀번호와 비교함.

6. zira's Zitto 4

AuthorLanguageUploadPlatformDifficultyQualityArch
zira(Visual) Basic5:06 PM 09/28/2024Windows2.54.0x86-64
Finding serial # and then create a keygen for this Keygenme 1

크랙미에서 쓰는 일부 VBVM 함수에 로그를 넣고 분석함.


_vbaVarTstEq

_vbaVarAdd

_vbaVarSub

_vbaLenVar

_vbaVarMul

_vbaVarMod

_vbaVarForInit

_vbaVarForNext

rtcLeftCharVar

rtcMidCharVar

rtcUpperCaseVar

_vbaVarCat

key는 이런 방식으로 생성함.

name: abc

key: CBA ABC CBA ABC CBA ABC ..

그 후 첫 20 글자가 사용됨.

left("CBAABCCBAABCCBAABCCBAABC", 20)

비밀번호의 각 글자는 이런 연산 루틴을 통해 만들어짐.


upper("C") -> C

sub(67, 48) //  'C' - '0' = 19

add(19, 0)  // 19 + 0

mul(19, 46) // ...

mul(0, 1)

mod(0, 17)

add(0, 106)

mod(106, 9)

add(1, 1)

add(1, 1)

로그를 보면서 keygen을 만들면 풀림.

7. Computerboy's Gemy

AuthorComputerboy
LanguageC/C++
Upload3:09 AM 11/22/2024
PlatformUnix/Linux etc.
Difficulty1.5
Quality2.5
Arch

The Gem Vault has been sealed, and only those who can break through its protections will be able to reveal its secrets. Inside lies a key to unlock the vault, but the path to the key is hidden behind layers of obfuscation.
Your task is to reverse engineer the binary, understand the underlying logic, and find the correct key that will open the vault. The key is not stored plainly in the binary, and it is generated dynamically at runtime.

UPX, 배열에 문자열 있음.

8. Zenton's Crack me for beginners

AuthorZenton
LanguageC/C++
Upload4:46 PM 11/24/2024
PlatformWindows
Difficulty1.0
Quality5.0
Archx86-64

A simple CrackMe that requires reversing a password check to find the correct password.

strcpy, strcmp

0개의 댓글