Shell_basic
-문제-
원격 서버에 /home/shell_basic/flag_name_is_loooooong경로에 flag파일이 있다. 플래그 값을 구해보자.
단, main 함수가 아닌 다른 함수들은 execve, execveat 시스템콜 사용을 못하도록 하며 풀이와 상관없다.
우선 서버에 접속해 보자.
서버에 접속해 보니 shellcode : 라고 쉘 코드를 입력하라는 텍스트가 뜬다.
그럼 원하는 경로에 있는 파일을 출력하는 쉘코드를 짠 다음 저곳에 보내면 flag가 출력될 거 같다.
쉘코드는 pwntools를 활용해서 만들면 쉽게 풀린다.(orw코드로 풀려했으나 어려워서 패스...)
우선 원하는 flag가 원격에 있는 서버에 있으니 remote함수로 접속하는 코드를 만들자.
그리고 그 서버가 64비트 기반인지 32비트 기반인지 입력하고 플래그가 들어있는 주소를 지정해 주자.
우선 시스템 콜을 차례대로 실행해야 하니 쉘코드를 초기화해주자.
시스템 콜을 써야 하는 이유?
main 함수가 아닌 다른 함수들이 이 시스템 콜을 사용할 수 없다는 조건이 있기 때문에, 파일 읽기와 출력 작업을 할 때 execve대신에 시스템 콜(open, read, write)을 사용해야 하기 때문!
그다음 flag위치의 파일을 열고 파일디스크립터(rax)로 파일의 내용을 읽고 스택(rsp)에 데이터를 저장하자.
스택(rsp)에 저장된 데이터를 표준출력(stdout(1))으로 출력해 주자.
맨 위의 사진에서 서버에 처음 접속하면 shellcode: 라는 메시지가 출력됐었다.
즉, 처음 서버를 실행했을 때 서버는 shellcode: 라는 메시지를 출력하면서 쉘 코드를 받을 준비가 됐다는 걸 나타냈었다.
그래서 print(p.recv())를 통해서 서버에서 오는 메시지를 출력시켜 서버가 준비가 됐는지 확인할 것이다. 만약 print(p.recv())를 처음에 실행시키지 않으면 서버가 준비되지 않은 상태에서 쉘코드를 받을 수 있으므로 먼저 실행시켜야 한다.
그다음 서버주소로 쉘코드를 보내자.(다만 서버의 CPU가 쉘 코드를 실행하려면 binary로 변환을 시켜주어야 한다. 그렇기 때문에 어셈블리어를 binary어로 바꿔주는 asm함수로 쉘코드를 변환시켜주자.)
마지막으로 서버가 보낸 flag값을 출력하면 끝이다.
그러면 이렇게 flag값이 나온다.
flag값 뒤에 나오는 \nong\x00... 은 처음에 데이터를 읽을 때 0x100(256바이트)로 지정해서 그렇다. 사진에서 보듯이 flag값의 출력값은 짧은데 빈 공간이 많아서 메모리에 남아있는 이전값이 그대로 출력된 것이다. (문제와는 큰 상관없다.)