이때 free는 해제한 메모리의 데이터를 초기화하지 않으므로, nametag에는 secret의 값이 일부 남아있게 됩니다
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct NameTag {
char team_name[16];
char name[32];
void (*func)();
};
struct Secret {
char secret_name[16];
char secret_info[32];
long code;
};
int main() {
int idx;
struct NameTag *nametag;
struct Secret *secret;
secret = malloc(sizeof(struct Secret));
strcpy(secret->secret_name, "ADMIN PASSWORD");
strcpy(secret->secret_info, "P@ssw0rd!@#");
secret->code = 0x1337;
free(secret);
secret = NULL;
nametag = malloc(sizeof(struct NameTag));
strcpy(nametag->team_name, "security team");
memcpy(nametag->name, "S", 1);
printf("Team Name: %s\n", nametag->team_name);
printf("Name: %s\n", nametag->name);
if (nametag->func) {
printf("Nametag function: %p\n", nametag->func);
nametag->func();
}
}
이코드에서 해제한 메모리의 데이터를 초기화하지않았다는데
secret = NULL 로 초기화한거 아닌가요?
여기서 해제한 메모리의 데이터를 초기화하지 않았다가 의미하는 바는,
secret
이 free() 이후 NULL로 초기화되기 전 본래 가리키던 메모리에 있는 데이터를 지우지 않았다는 뜻으로
이해할 수 있을 것 같습니다.
즉, 32번 라인의 secret = NULL;
이 실행됨으로써 secret
이 NULL로 초기화되는 것은 맞지만,
아직 메모리에는 "ADMIN PASSWORD"
, "P@ssw0rd!@#"
, 0x1337
과 같은 데이터가 남아있는 상태인 것이죠.
(엄밀히 따지면 "ADMIN PASSWORD"
, "P@ssw0rd!@#"
, 0x1337
과 같은 데이터 일부분이 남아있게됨)
가령 해제한 메모리의 데이터를 초기화했다고 말할 수 있으려면,
// Name: uaf.c
// Compile: gcc -o uaf uaf.c -no-pie
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct NameTag {
char team_name[16];
char name[32];
void (*func)();
};
struct Secret {
char secret_name[16];
char secret_info[32];
long code;
};
int main() {
int idx;
struct NameTag *nametag;
struct Secret *secret;
secret = malloc(sizeof(struct Secret));
strcpy(secret->secret_name, "ADMIN PASSWORD");
strcpy(secret->secret_info, "P@ssw0rd!@#");
secret->code = 0x1337;
memset(secret, 0x00, sizeof(struct Secret)); // 요부분이 패치된 부분!
free(secret);
secret = NULL;
nametag = malloc(sizeof(struct NameTag));
strcpy(nametag->team_name, "security team");
memcpy(nametag->name, "S", 1);
printf("Team Name: %s\n", nametag->team_name);
printf("Name: %s\n", nametag->name);
if (nametag->func) {
printf("Nametag function: %p\n", nametag->func);
nametag->func();
}
}
위와 같이 secret->code = 0x1337;
와 free(secret);
사이에
memset(secret, 0x00, sizeof(struct Secret));
를 넣어주는 식으로 패치하면 될 것 같습니다.
이렇게 하면 secret
이 NULL로 초기화되기 전 본래 가리키던 메모리에 있는 데이터를 다 널바이트(0x00)로 밀어버리기 때문에,
해제한 메모리에 "ADMIN PASSWORD"
, "P@ssw0rd!@#"
, 0x1337
과 같은 데이터가 남아있지 않겠죠?