challenge : https://crackmes.one/crackme/5ed3cd9a33c5d449d91ae6b1
official writeup :
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.
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!!