guessme

 

challenge : https://crackmes.one/crackme/5ed3cd9a33c5d449d91ae6b1

official writeup :

guessmeoriginal

my writeup

First did the standard file command and changed the execution permission chmod +x guessme

When executed it asks for a guess, which you have to find to get the secret message.

image

so I disassembelled it using ghidra

the decompiled main function :

ulong main(void)

{
  int anotherthing;
  basic_ostream *this;
  long in_FS_OFFSET;
  bool bVar1;
  int local_7c;
  int password;
  undefined4 local_74;
  long seconds;
  long microseconds;
  long something;
  timeval TIME;
  basic_string<char,std--char_traits<char>,std--allocator<char>> local_48 [40];
  long local_20;
  
  local_20 = *(long *)(in_FS_OFFSET + 0x28);
  allocator();
  basic_string((char *)local_48,(allocator *)&DAT_00102009);
  ~allocator((allocator<char> *)&TIME);
  gettimeofday(&TIME,(__timezone_ptr_t)0x0);
  seconds = TIME.tv_sec;
  microseconds = TIME.tv_usec;
  something = (long)((double)TIME.tv_usec / 1000.00000000 + (double)(TIME.tv_sec * 1000));
  anotherthing = cross_sum(TIME.tv_usec);
  **password** = (int)(something % (anotherthing * microseconds));
  local_74 = 0x42;
  operator<<<std--char_traits<char>>((basic_ostream *)cout,"Your guess: ");
  operator>>((basic_istream<char,std--char_traits<char>> *)cin,&local_7c);
  bVar1 = password != local_7c;
  if (bVar1) {
    this = operator<<<std--char_traits<char>>((basic_ostream *)cout,"S0RRY!");
    operator<<((basic_ostream<char,std--char_traits<char>> *)this,endl<char,std--char_traits<char>>)
    ;
  }
  else {
    this = operator<<<std--char_traits<char>>((basic_ostream *)cout,"R");
    this = operator<<<std--char_traits<char>>(this,"z");
    this = operator<<<std--char_traits<char>>(this,'A');
    this = operator<<<std--char_traits<char>>(this,"w");
    this = operator<<<std--char_traits<char>>(this,"R");
    this = operator<<<std--char_traits<char>>(this,'C');
    this = operator<<<std--char_traits<char>>(this,(char)local_74);
    operator<<<char,std--char_traits<char>,std--allocator<char>>(this,(basic_string *)local_48);
    this = operator<<<std--char_traits<char>>((basic_ostream *)cout,"IhC");
    this = operator<<<std--char_traits<char>>(this,"g");
    operator<<((basic_ostream<char,std--char_traits<char>> *)this,endl<char,std--char_traits<char>>)
    ;
  }
  ~basic_string(local_48);
  if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return (ulong)bVar1;
}

you can see that the secret message can be found out easily by joining the individual characters towards the end or simply pathing the binary from jnz to jz and running program. So that’s that.

But the real task is to get the secret message using the correct guess.

When you explore the code , you’ll notice gettimeoftheday function has been called and the password has been made out of the time, so the password depends upon the current time.

So the approach should be to run the program , pause it after the the password has been calculated from TIME and then print the value of the password variable and then continue the program and enter that password.

So I used gdb :

 gdb  guessme
(gdb) disas main
Dump of assembler code for function main:
   0x000000000000131f <+0>:	push   %rbp
   0x0000000000001320 <+1>:	mov    %rsp,%rbp
   0x0000000000001323 <+4>:	push   %rbx
   0x0000000000001324 <+5>:	sub    $0x78,%rsp
   0x0000000000001328 <+9>:	mov    %fs:0x28,%rax
   0x0000000000001331 <+18>:	mov    %rax,-0x18(%rbp)
   0x0000000000001335 <+22>:	xor    %eax,%eax
   0x0000000000001337 <+24>:	lea    -0x50(%rbp),%rax
   0x000000000000133b <+28>:	mov    %rax,%rdi
   0x000000000000133e <+31>:	callq  0x1110 <_ZNSaIcEC1Ev@plt>
   0x0000000000001343 <+36>:	lea    -0x50(%rbp),%rdx
   0x0000000000001347 <+40>:	lea    -0x40(%rbp),%rax
   0x000000000000134b <+44>:	lea    0xcb7(%rip),%rsi        # 0x2009
   0x0000000000001352 <+51>:	mov    %rax,%rdi
   0x0000000000001355 <+54>:	callq  0x10d0 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcRKS3_@plt>
   0x000000000000135a <+59>:	lea    -0x50(%rbp),%rax
   0x000000000000135e <+63>:	mov    %rax,%rdi
   0x0000000000001361 <+66>:	callq  0x10a0 <_ZNSaIcED1Ev@plt>
   0x0000000000001366 <+71>:	lea    -0x50(%rbp),%rax
   0x000000000000136a <+75>:	mov    $0x0,%esi
   0x000000000000136f <+80>:	mov    %rax,%rdi
   0x0000000000001372 <+83>:	callq  0x10f0 <gettimeofday@plt>
   0x0000000000001377 <+88>:	mov    -0x50(%rbp),%rax
   0x000000000000137b <+92>:	mov    %rax,-0x68(%rbp)
   0x000000000000137f <+96>:	mov    -0x48(%rbp),%rax
   0x0000000000001383 <+100>:	mov    %rax,-0x60(%rbp)
   0x0000000000001387 <+104>:	mov    -0x68(%rbp),%rax
   0x000000000000138b <+108>:	imul   $0x3e8,%rax,%rax
   0x0000000000001392 <+115>:	pxor   %xmm1,%xmm1
   0x0000000000001396 <+119>:	cvtsi2sd %rax,%xmm1
   0x000000000000139b <+124>:	pxor   %xmm0,%xmm0
   0x000000000000139f <+128>:	cvtsi2sdq -0x60(%rbp),%xmm0
   0x00000000000013a5 <+134>:	movsd  0xc8b(%rip),%xmm2        # 0x2038
   0x00000000000013ad <+142>:	divsd  %xmm2,%xmm0
   0x00000000000013b1 <+146>:	addsd  %xmm1,%xmm0
   0x00000000000013b5 <+150>:	cvttsd2si %xmm0,%rax
   0x00000000000013ba <+155>:	mov    %rax,-0x58(%rbp)
   0x00000000000013be <+159>:	mov    -0x60(%rbp),%rax
--Type <RET> for more, q to quit, c to continue without paging--
   0x00000000000013c2 <+163>:	mov    %rax,%rdi
   0x00000000000013c5 <+166>:	callq  0x124d <_Z9cross_suml>
   0x00000000000013ca <+171>:	cltq   
   0x00000000000013cc <+173>:	imul   -0x60(%rbp),%rax
   0x00000000000013d1 <+178>:	mov    %rax,%rcx
   0x00000000000013d4 <+181>:	mov    -0x58(%rbp),%rax
   0x00000000000013d8 <+185>:	cqto   
   0x00000000000013da <+187>:	idiv   %rcx
   0x00000000000013dd <+190>:	mov    %rdx,%rax
   0x00000000000013e0 <+193>:	mov    %eax,-0x70(%rbp)

using your excellent assembly language skills or else using ghidra you can figure out which line corresponds to the value of password being stored.

Here it is the last line mov %eax,-0x70(%rbp) means store value of eax into (rbp - 0x70) which is the location of password variable.

So we break just after that.

[ It would be easier to get the variable location from ghidra, but for some reason it was showing the location as rbp - 0x78 so I used the gdb disas]

(gdb) b *main+196
Breakpoint 1 at 0x13e3

Now we run the program and examine rbp - 0x70

(gdb) r
Starting program: /home/utk/Downloads/crackme/guessme 

Breakpoint 1, 0x00005555555553e3 in main ()
(gdb) x/d $rbp - 0x70
0x7fffffffddf0:	1330399
(gdb) c
Continuing.
Your guess: 1330399
RzAwRCBKMEIhCg
[Inferior 1 (process 8205) exited normally]
(gdb)

Yay!!