Skip to content

Latest commit

 

History

History
79 lines (76 loc) · 2.93 KB

singlehell.md

File metadata and controls

79 lines (76 loc) · 2.93 KB

singlehell (250)

solution

先用strings看程式,發現經過upx加殼,因此先以upx -d脫殼,接著以IDA進行反編譯,稍微trace一下可以看到接收回應的部分

__int64 __fastcall get_response(__int64 response)
{
  __int64 result; // rax
  void *reward; // rax
  unsigned int player_damage; // ebp
  __int64 monster_hp; // rbx

  result = decode4(response);
  if ( (_DWORD)result == 2 )
  {
    player_damage = decode4(response);
    monster_hp = decode8(response);
    PlayerHP -= player_damage;
    result = __printf_chk(1LL, "[Info] Player is Damaged: %d\n", player_damage);
    MonsterHP = monster_hp;
  }
  else if ( (_DWORD)result == 7 )
  {
    puts("[Info] Congratulation !");
    reward = decode_str(response);
    result = __printf_chk(1LL, "[Info] Here is your reward : %s\n", reward);
  }
  return result;
}

這邊會接收server的回應,若是2則減少player的血量,並設定monster的血量,若是7則顯示reward。 由於monster的血量是根據server送來的回應設定的,因此應該無法修改,但是player是用扣的,因此試著將player扣血的部分

400ecb:       29 2d ef 11 20 00       sub    DWORD PTR [rip+0x2011ef],ebp

全部patch成nop,測試後成功,player無論如何都不會受傷,server也沒有進行檢查。

但是由於怪物血量太高,傷害還是太小,因此接著試著看看攻擊的部分:

bool Attack()
{
  ...
  srand(time(0LL));
  rand_num = random();
  v7 = 8;
  v8 = 1;
  i = 0LL;
  v3 = rand_num
     - 10
     * (((signed __int64)((unsigned __int128)(0x6666666666666667LL * (signed __int128)rand_num) >> 64) >> 2)
      - (rand_num >> 63));
  v9 = rand_num
     - 10
     * (((signed __int64)((unsigned __int128)(0x6666666666666667LL * (signed __int128)rand_num) >> 64) >> 2)
      - (rand_num >> 63));
  do
  {
    v4 = (char *)&v8 + i++;
    *v4 ^= xor_code2[i];
  }
  while ( i != 8 );
  bytes_sent = send(fd, &v7, 0xCuLL, 0);
  if ( bytes_sent > 0 )
    __printf_chk(1LL, "[Info] Attack Monster with Damage: %d\n", v3);
  return bytes_sent > 0;
}

攻擊的傷害是隨機的,因此應該和rand_num有關,在設定rand_num的部分

  400c94:       e8 d7 fb ff ff          call   400870 <random@plt>
  400c99:       48 ba 67 66 66 66 66    movabs rdx,0x6666666666666667
  400ca0:       66 66 66
  400ca3:       48 89 c1                mov    rcx,rax
  400ca6:       48 8d 7c 24 04          lea    rdi,[rsp+0x4]
  400cab:       48 f7 ea                imul   rdx
  400cae:       48 89 c8                mov    rax,rcx

可以觀察到rax會複製給rcx再複製回rax,利用這點,試著將mov rcx,raxpatch為mov rcx,rdx,這樣rand_num就會變為0x6666666666666667,實際測試後發現傷害增加非常多,因此以簡單的script不斷送攻擊請求等數十秒即可拿到flag了。

因為monster死後server似乎不會結束,所以最後會額外多幾個loop,導致要往回找一些才能看到flag。