Skip to content

Latest commit

 

History

History
98 lines (90 loc) · 2.87 KB

File metadata and controls

98 lines (90 loc) · 2.87 KB

babygame01

In this challenge, picoCTF provides a binary without libc library.

I encountered an issue when trying to run the provided binary from picoCTF. The error message displayed was:

./game: /lib32/libc.so.6: version `GLIBC_2.34' not found (required by ./game)

To resolve this issue, I downloaded glibc version 2.34 and compiled it locally. Now, I need to ensure that the binary uses this specific version of the libc library. This can be achieved by using the patchelf tool.

First, let's check the current rpath (run-time library search path) of the binary:

patchelf --print-rpath ./game
libc.so.6

Next, we can replace the needed library with the newly compiled libc.so.6 using the following command:

patchelf --replace-needed libc.so.6 $(pwd)/libc.so.6 ./game1

By executing these steps, the binary should now run without any issues.

Let's look at the code

int main(void) {
  int step;
  int in_GS_OFFSET;
  int player;
  int local_aa8;
  char local_aa4;
  undefined map [2700];
  int local_14;
  undefined *local_10;
  
  local_10 = &stack0x00000004;
  local_14 = *(int *)(in_GS_OFFSET + 0x14);
  init_player(&player);
  init_map(map,&player);
  print_map(map,&player);
  signal(2,sigint_handler);
  do {
    do {
      step = getchar();
      move_player(&player,(int)(char)step,map);
      print_map(map,&player);
    } while (player != 0x1d);
  } while (local_aa8 != 0x59);
  puts("You win!");
  if (local_aa4 != '\0') {
    puts("flage");
    win();
    fflush(stdout);
  }
  step = 0;
  if (local_14 != *(int *)(in_GS_OFFSET + 0x14)) {
    step = __stack_chk_fail_local();
  }
  return step;
}

To win this CTF, it is evident that we must successfully satisfy the following if condition:

if (local_aa4 != '\0')

Let's look at the local variables.

Alt text In order to achieve our goal, we need to navigate to the offset of -0xaa4 within the map. The map itself is located at -0xaa0 which is approximately -2700 bytes away from the esp.

Upon examining the move_player function, we can observe that there are no boundary checks implemented. As a result, we simply need to move to the cell at the offset of -4 within the array, which will overwrite the checked value.

void move_player(int *player,char step,int map) {
  int iVar1;
  
  if (step == 'l') {
    iVar1 = getchar();
    player_tile = (undefined)iVar1;
  }
  if (step == 'p') {
    solve_round(map,player);
  }
  *(undefined *)(*player * 0x5a + map + player[1]) = 0x2e;
  if (step == 'w') {
    *player = *player + -1;
  }
  else if (step == 's') {
    *player = *player + 1;
  }
  else if (step == 'a') {
    player[1] = player[1] + -1;
  }
  else if (step == 'd') {
    player[1] = player[1] + 1;
  }
  *(undefined *)(*player * 0x5a + map + player[1]) = player_tile;
  return;
}

That's it, Thanks for reading.