gets를 이용한 코드에서
#include <stdio.h>
#include <ctype.h>
#define H2D(x) ((x)<='9'?(x)-'0':(toupper(x))-'A'+10) //16進数1桁の文字を数値に
// 0-9,a-f,A-Fのみ正しく動作する
static char st1[] = "This is a pen.";
static char st2[] = "I have an apple.";
// 目標:入力だけでこの関数を実行する
void sub2(void) {
printf("Bingo!\n");
}
// gets()を使った危険な関数
int sub1(int hint) {
char *p = st1;
char str[] = "Hello, World!!!";
char buf[32]; // gets()で入力される文字列のバッファ(小さいのですぐ溢れる)
char *s,*d;
// ヒントとして各変数や関数のアドレスを出す
if (hint) {
printf("各変数が格納されているアドレス:\n");
printf("st1 : %p\n", st1);
printf("st2 : %p\n", st2);
printf("d : %p\n", &d);
printf("s : %p\n", &s);
printf("buf : %p\n", buf);
printf("str : %p\n", str);
printf("p : %p\n", &p);
printf("各関数のアドレス:\n");
printf("sub1 : %p\n", sub1);
printf("sub2 : %p\n\n", sub2);
}
puts("文字列を入力:");
gets(buf);
// bufに入力された文字列に%xxという形式の部分があれば
// xxを16進数とみなして1バイトの値に置き換える
s = d = buf; // sは入力文字、dは変換後を指すポインタ
// 変換後のデータはbufに上書きされていく
do {
if(*s == '%') { // %があれば
*d = H2D(*(s+1))*16+H2D(*(s+2)); // 16進数2桁の文字を数値に
s+=3; // %xx
d++;
} else {
*d++ = *s++;
}
} while(*d);
puts("\n出力文字列:");
puts(buf);
puts(str);
if (hint) {
printf("ヒント:pの値 %p\n", p);
}
puts(p);
return 0; // 返却値はいつも0のはず
}
int main(int argc, char *argv[]) {
int r;
char buf[4096]; // バッファオーバーフローしやすいように空間を空けてある
r = sub1(argc > 1); // 引数があればヒントを出すように
printf("sub1() returns %d\n", r); // sub1()の返り値表示
return 0;
}
이 코드를 실행했을때
welcome 을 입력하면
welcome이 첫번째줄
hello, woreld가 두번째
This is a pen 이 세번째 줄로 나올때
32bit가 넘는 입력을 하였을때는
이렇게 두번째줄이 welcome으로 변합니다.
하지만 세번째 줄을 바꿀려고 한다면 어떤 입력을 해야되는지 감이 안잡힙니다... 어떤식으로 하여야 될까요?? 질문이 처음이라 내용에서 이해 안되시는 부분이 있으면 말해주세요
헛회원
C에서 벗어나서 Golang을 쓰자이제 ㅎㅎㅎ
뱀고기
출력문자열 세번째는 p인데 st1 배열 내용을 바꿔야되지 않을까
그리고 힌트로 변수들 주소 보고 변수들 배치를 봐야됨
버퍼 오버플로우로 얼마나 덮어써야 하는지 나올듯
티벳여우
1. buf 덮으려고 32byte 넣고
2. str 덮으려고 17 ~ 24바이트정도 넣으면 될건데 스택에 몇바이트 잡혔는지는 gdb로 까보거나 1바이트씩 늘려가면서 세그먼테이션 폴트 뜨는 바이트 수 확인하면 됨
3. 그 뒤로 출력 원하는 문자열 주소 넣으면 될 듯
4. 추가로 4byte 더미 넣어서 SFP 대충 덮어씌우고 ret주소 4바이트를 sub2 주소 넣으면 bingo 까지 뜰거
VisualArt
정말정말 감사합니다. 안되서 답답했는데 ㅠㅠ