one_gadget. constraints analyze & troubleshooting

one_gadget은 어떤 버젼의 libc냐의 따라 완전히 constraints이 달라지게 된다. 그중 최근의 Dreamhack 문제를 풀면서 해결한 문제의 대해서 다룬다.

일반적으로 최근버젼의 libc에 대해서 one_gadget을 실행하면

C
(pwn) amemoyoi ~$ one_gadget /lib/i386-linux-gnu/libc.so.6
0xe2ff0 execve("/bin/sh", [ebp-0x30], esi)
constraints:
  address ebp-0x24 is writable
  [ebp-0x2c] is the GOT address of libc
  [[ebp-0x30]] == NULL || [ebp-0x30] == NULL || [ebp-0x30] is a valid argv
  [esi] == NULL || esi == NULL || esi is a valid envp

0xe2ff3 execve("/bin/sh", [ebp-0x30], esi)
constraints:
  address ebp-0x24 is writable
  ecx is the GOT address of libc
  [[ebp-0x30]] == NULL || [ebp-0x30] == NULL || [ebp-0x30] is a valid argv
  [esi] == NULL || esi == NULL || esi is a valid envp

0xe2ff9 execve("/bin/sh", [ebp-0x30], esi)
constraints:
  address ebp-0x20 is writable
  ecx is the GOT address of libc
  [[ebp-0x30]] == NULL || [ebp-0x30] == NULL || [ebp-0x30] is a valid argv
  [esi] == NULL || esi == NULL || esi is a valid envp

0xe3000 execve("/bin/sh", [ebp-0x30], esi)
constraints:
  address ebp-0x30 is writable
  ecx is the GOT address of libc
  [[ebp-0x30]] == NULL || [ebp-0x30] == NULL || [ebp-0x30] is a valid argv
  [esi] == NULL || esi == NULL || esi is a valid envp

0x17e0b1 execl("/bin/sh", eax)
constraints:
  esi is the GOT address of libc
  eax == NULL

0x17e0b2 execl("/bin/sh", [esp])
constraints:
  esi is the GOT address of libc
  [esp] == NULL

다음과 같이 나오게 된다.

많은 제약조건들이 있음을 알 수 있다. 근데 자세히 보면 is the GOT address of libc 이 문장이 필수로 포함되어 있다. 이게 어떤 조건을 말하는 것이고 왜 필요한지 알아보자

일단 가장 쉬운 조건은 주로

C
0x17e0b1 execl("/bin/sh", eax)
constraints:
  esi is the GOT address of libc
  eax == NULL

이런 형태이다. eax == NULL도 return 0; 문장이 있다면 바로 충족이 가능하기 때문이다. 따라서 이 조건을 만족시키겠다.

libc의 0x17e0b1 오프셋에는 사진과 같은 코드가 존재한다.

자세히 보면 $esi ( X86 문제라서 ) 에 특정 오프셋값을 빼고 그 값을 스택에 넣고 execl 함수를 실행한다. execl 함수는 execve 함수와 같은 맥락을 가진다.

따라서 저 %eax 에는 “/bin/sh”의 주소가 들어가야 한다.

원래 의도도 같다. 저 %eax에 “/bin/sh”의 주소가 들어가게 설계가 되어 있다.

즉, 원래 %esi 값에 조건 대로

esi is the GOT address of libc 라는 것이다.

C
(pwn) amemoyoi ~$ objdump -h /lib/i386-linux-gnu/libc.so.6 | grep .got
 13 .plt.got      00000010  00023190  00023190  00023190  2**3
 26 .got          000001cc  00230e34  00230e34  00230e34  2**2

다음과 같이 오프셋을 알 수 있고 그러면 libc_base + 00230e34 의 값을 $esi에 넣으면 된다.