

Canary있고, 쉘코드 사용 불가다.
소스코드 분석부터 진행하겠다.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
char name[16];
char *command[10] = { "cat",
"ls",
"id",
"ps",
"file ./oob" };
void alarm_handler()
{
puts("TIME OUT");
exit(-1);
}
void initialize()
{
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
int main()
{
int idx;
initialize();
printf("Admin name: ");
read(0, name, sizeof(name));
printf("What do you want?: ");
scanf("%d", &idx);
system(command[idx]);
return 0;
}
name[16]char *command[10] = {"cat","ls","id","ps","file ./oob"};read(0, name, sizeof(name)); 로 16바이트를 그대로 읽음scanf("%d", &idx); 로 정수 인덱스 입력system(command[idx]); 호출idx에 대한 범위 검증이 없어서,
command[idx]가 배열 경계를 벗어나 임의 주소를 문자 포인터로 해석해 system()의 인자로 해석되는 부분이 문제다.
즉, name에 명령 문자열의 주소를 써 넣고, idx를 그 위치로 가리키게 하면 system()이 문자열을 그대로 실행한다.
헷갈릴만한 포인트는 name에 “/bin/sh”가 아닌 &”/bin/sh” 가 들어간다는 점인데,
command 버퍼가 문자열을 담는 배열이 아닌 문자열 주소를 담는 포인터 배열이기 때문이다.
즉, “/bin/sh”에 접근하기 위해서는 &”/bin/sh” 를 저장해야한다.

command = 0x0804a060