해당 문제 관련해서 질문 드릴게 있습니다.
  1. 해당 코드에서 사용되는 buf는 0x50사이즈인 반면, buf와 canary의 byte차이는 0x58입니다. 추가적인 8byte는 어디서 온 건가요? 단순한 Byte padding인가요?

  2. 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
고기
대표 업적 없음
  1. 스택 정렬(Stack alignment)에 의해 생긴 dummy입니다. x86-64에서 스택 포인터는 항상 16바이트 단위로 정렬되어야 하기 때문에 0x58 바이트의 스택을 확보하는 것이 아닌 0x60 바이트를 확보합니다.
  2. 버퍼의 주소는 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 가 됩니다.

2024.08.14. 20:05
질문에 대한 답을 알고 계신가요?
지식을 나누고 포인트를 획득해보세요.
답변하고 포인트 받기