해당 문제 관련해서 질문 드릴게 있습니다.
-
해당 코드에서 사용되는 buf는 0x50사이즈인 반면, buf와 canary의 byte차이는 0x58입니다. 추가적인 8byte는 어디서 온 건가요? 단순한 Byte padding인가요?
-
canary값을 받는 것에 대한 질문이 있습니다.
버퍼의 주소의 경우 다음과 같은 코드로 입력값을 받아왔습니다.
buf = int(p.recvline()[0:-1], 16)
slog('Address of buf', buf)
그리고 canary값은 다음과 같은 코드로 입력값을 받고 있습니다.
raw_canary = p.recvn(7)
print ("RAW_CANARY : ", raw_canary)
cnry = u64(b'\x00' + raw_data)
slog("canary : ", cnry)
해당 코드로 받은 데이터는 다음과 같습니다.
raw_canary = 0x 41 0e ce 75 fe 86 81 (little endian)
cnry = 0x 81 86 fe 75 ce 0e 41 00 (big endian)
여기서 궁금한게, buf는 단순히 받으면 본래 buf의 주소값이 받아져서, 별다른 데이터 핸들링이 필요가 없이 big endian으로 잘 받아지는데, canary의 경우 little endian 데이터로 받아지고 이를 u64를 써서 big endian unpacking해줘야 하는 이유를 잘 모르겠습니다.
이 지점에서 많이 헷갈리고 있는데, 도움 부탁드립니다.
#pwnable
작성자 정보
답변
1
고기
대표 업적 없음
- 스택 정렬(Stack alignment)에 의해 생긴 dummy입니다. x86-64에서 스택 포인터는 항상 16바이트 단위로 정렬되어야 하기 때문에 0x58 바이트의 스택을 확보하는 것이 아닌 0x60 바이트를 확보합니다.
- 버퍼의 주소는
printf()
함수에서%p
형식으로 출력되고 있기 때문에 별도의 데이터 핸들링 없이 그대로 사용할 수 있습니다. 반면 카나리 값은%s
형식으로 출력 되기 때문에 낮은 주소부터 1 바이트 씩 출력 되어 뒤집힌 값이 나오게 되는 것입니다.
예를 들어 보면,
0x1000 번지 : 0x41
0x1001 번지 : 0x42
0x1002 번지 : 0x43
0x1003 번지 : 0x44
0x1004 번지 : 0x45
0x1005 번지 : 0x46
0x1006 번지 : 0x47
0x1007 번지 : 0x00
위와 같은 값이 저장된 메모리가 있고, char[8] buf 의 시작 주소가 0x1000 (buf == 0x1000) 이라고 가정해봅니다.
이 때, printf("%p", buf);
의 결과는 0x1000
이 될 것이고, printf("%s", &buf);
의 결과는 ABCDEFG
가 됩니다.