Ya-Wen Jeng
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
# IT Security 2 (Ch7~Ch8) ## Chapter 7: Buffer Overflows and other Memory Corruptions ### :cactus: Buffer Overflow - :droplet: *定義* - A condition at an interface under which **more input** can be placed into a buffer than the capacity allocated for it, **overwriting** other information. Attackers exploit such a condition to crash a system or to insert specially crafted code that allows them to gain control of the system. - C語言 - 預設programmer要負責**data integrity** - compiler不做integrity檢查 - 可能造成超過memory space的capacity buffer會overwriting接下來的資料 - 多數情況會crash program - **ping of death** - 基本buffer overflow - **Variable corruption** - 利用過長的input data複寫其他data - Corruption of program control addresses - 以更改程式執行順序 - 攻擊者必須: - identify overflow vulnerability - buffer要存什麼資料 - 要怎麼corrupt memory allocation ### :cactus: Executable Program Segments <table> <tr> <td rowspan=2> Dynamic </td> <td> Stack segment </td> </tr> <tr> <td> Heap segment </td> </tr> <tr> <td rowspan=3> Static </td> <td> Bss segment </td> </tr> <tr> <td> Data segment </td> </tr> <tr> <td> Text segment </td> </tr> </table> - :droplet: *Text segment* - **code**,儲存machine language instructions - nonlinear執行 - 當程式執行時,**Extended Instruction Pointer (EIP)** 設為text segment的第一個instruction 1. 讀取指向的instruction 2. Adds the byte length of the instruction to EIP 增加instruction的byte長度給EIP 3. 執行instruction 4. 回到步驟1 - 不允許write (不允許修改code) - :droplet: *Data segment* - 初始化過的global和static變數 - writable - fixed size - :droplet: *Bss segment* - 非初始化過的counter - writable - fixed size - :droplet: *Heap segment* - **programmer** 可以直接控制的memory片段 - 被allocator和deallocator algorithm控制 - reserve region of memory - release reservation - :droplet: *Stack segment* - 在 **function calls** 暫時儲存的空間 - stack frame儲存 - 輸入變數 (passed variables) - 2 pointers: - **Saved frame pointer (SFP):** 恢復Extended stack pointer,指向stack的尾端 - **return address (RET):** 恢復EIP,指向下個instruction - 區域變數 (local variable) - 在每個function call時產生 - Stack Example ```cpp=1 void test_function(int a, int b, int c, int d) { int flag; char buffer[10]; flag = 31337; buffer[0] = 'A'; } int main(){ test_function(1,2,3,4); } ``` | Stack | | -------- | | </br>| | d| |c| |b| |a| |RET| |SFP| |flag| |buffer| - :droplet: Memory exploits - **Buffer** 是指memory中的data storage area (stack or heap) - 若 **executable code** 被當作 **data** 提供,使用者可能被騙執行 - pointer assignment - format strings - memory allocation/ de-allocation - function pointers - calls to library routines via offset tables - 若buffer塞了過多東西 - 原: ```cpp= void func(char *str){ char buf[126]; strcpy(buf, str); } ``` | buf | SFP | REP | str | ... | | --- | --- | --- | --- | --- | - Overflow: 複寫鄰近的stack區塊 | buf | overflow | str | ... | | --- | --- | --- | --- | > 複寫的區域會被認為是 return address - 攻擊者利用此 return address 執行自己的input eg. `execve("/bin/sh")` - 則攻擊者可以得到 shell 若victim program是 `setuid root` 則可得到 root shell ### :cactus: Different ways of executing attack code :one: Attack 1. :droplet: 使return address改成指向attack code 2. :droplet: **return-to-libc:** 用現有的instructions eg. `system()`, `exec()` - stack理論上只能存data但攻擊者存了executable code - buffer的RET必有**correct address of attack code** - 否則程式會crash - 攻擊者要正確猜到在buffer的哪個位置 ### :cactus: Shell Code - buffer overflow攻擊的最重要的部分 - **transfer of execution to code** - 因shell code用來執行user command-line interpreter - Unix: `execve("/bin/sh")` - Windows: `system("command.exe")` - 通常針對不同的OS攻擊,因為指令不一樣 - buffer overflow需要 - 避免library calls(`execve()`) :question: - position independent, 只有相對位址 - 不能有NULL,否則會被視為string的結尾 ### :cactus: Format string in C - 沒有check input size - `strcpy` - `strcat` - `gets` - `scanf` - `printf` - Range checking: - `strncpy` 只有最多`n`個字被複製 - `strncat` 首`n`個`*src`才能被複製到`*dest`中 - 可能的overflow: ```c strcpy(record, user); strcat(record,":"); strcat(record, cpw); ``` - "fix": ```c strncpy(record, user, MAX_STRING_LEN-1); strcat(record,":"); strncat(record, cpw, MAX_STRING_LEN-1); ``` > `record = record||":"||cpw` > 問題: 只有`MAX_STRING_LEN-1`長度的record被allocated > :two: Attack - :droplet: 修改function pointer指向attack code - :droplet: 任何memory可以被此儲存值進pointer的statement修改 ### :cactus: Off-by-one Overflow - `for (i=0; i<=512; i++)` 會copy 513個字元 > 不能change RET,但可能change SFP to前一個stack frame :three: Attack - Overflow **Frame Pointer** 以取代 stack frame - 修改原本的 frame pointer 成 attacker-controlled memory - 可以用 **off-by-one** overflow 達成 - 但attacker必須猜到fake frame的address ### :cactus: Heap Overflow - 可能修改 function pointer 指向重要的資料 - **illegitimate privilege elevation:** 若 program 有 root 權限,則攻擊者可以存取權限較高的檔案 - Heap: | Buf[256] | | vtable |... | ptr| | -------- | -------- | -------- |-------- |-------- | - 若`Buf`overflow,則會蓋住`vtable` - `ptr`指向的`vtable`的位址會變成overflow的data (eg. shell code) - :droplet: Heap Spraying - 用 Javascript 和 shellcode spray heap - 並在spray area任意地方指向vtable pointer - 指向任意在heap中的 function pointer 會執行shellcode ### Dynamic Memory Management in C - `malloc(size_t n)` - 分配 `n` bytes 並回傳一個指標 - memory不是乾淨的 - `free(void *p)` - 釋放 `p` 指標指向的memory space - 錯誤: - Initialization errors - Failing to check return values - writing to already freed memory - freeing the same memory more than once - improperly paired memory management functions (eg. `malloc`/`delete`) - Failure to distinguish scalars and arrays - improper use of allocation functions > all result in exploitable vulnerabilities ### Variable Arguments in C - `printf` 可以有可變的輸入數量 - `printf("hello, world");` - `printf("length of '%s' = %d", str, str.length());` - 在執行時多了變數`va_start`, `va_arg`, `va_end` - Format Strings - 正確的: `printf("foo = %d", foo);` - Sloppy use: `char buf[123]="hello world; printf(buf);` (正確用法: `printf("%s", buf);`) - 若buffer裡面有 `%` ,則原本的stack pointer會以為是argument - :japanese_goblin: attacker可以用來移動stack pointer - `%n`: 印出的字元數量 - 若 ```c char buf[16] = "overflow this!%n"; printf(buf); ``` - stack pointer指向的位置會被譯為number of characters將要被寫入的位址 > 如 > `printf("overflow this!%n", &myVar);` > `%n` 為將要被寫入的位址 - | attackString%n, attack code | | &RET |... | RET | | -------- | -------- | -------- |-------- |-------- | `RET`會指向`attack code`, `printf(buffer)`會寫入 `attackString` 的number of characters 到 `RET` 中 > C 有一簡單的方式print出多個 symbols: `%Mx` 會print出剛好 `M` bytes > 若`attackString`有足夠多的`%Mx`,長度等於attack code的address的most significant byte,則此byte會被寫入`&RET`中 > 再執行3次 `&RET+1`,`&RET+2`,`&RET+3`會得到所有attack code的address > 把`RET`複寫為attack code的address ### :cactus: Preventing Buffer Overflows - :droplet: 分為兩類 - :one: **Compile time:** - 選擇不允許buffer overflow的high level programming language - 有些library仍vulnerable - 無法直接取得hardware resources - safe coding - safe libraries - additional code to detect(eg. stackGuard) - :bird: **StackGuard** - 在stack frame加入一個 **Canary** ,在function return前檢查 **Integrity** - | buf | <font color=red>Canary</font> | SFP | RET | | --- | --- | --- | --- | 若 `buf` overflow 的話會改變 Canary - 兩種 canary: 1. Random number 2. termination symbol: `\0`, `EOF` 就不會被`strcpy`就不會繼續copy - 需要code **re**compilation - 每個function都要檢查會降低performance - 放在`buf` 和 `pointer` 旁邊更降低performance - 可以被攻擊 - :penguin: 攻擊StackGuard - 用`strcpy` 複寫pointer,指向RET - `strcpy` 可以複寫而且避開 Canary - :statue_of_liberty: **LibSafe** - 動態載入的library - 攔截calls eg.`strcpy` - 檢查現在的stack frame有沒有足夠的空間 - `|frame-pointer – dest| > strlen(src)` - :point_up: **PointGuard** - attack: overflow a function pointer以指向attack code - 在memory中 **Encrypt all pointers** - 執行時產生一 **random key** - XOR each pointer - 攻擊者不能預測 - 即使此key被攻擊者複寫,XOR 後此key會被 **dereference** to a random address > 根據被攻擊過的key decrypt過後,會指向一random address > 因為修改的key不會是attack code address本身 - :two: **Run-time:** - attack: 利用 **Code Injectoin** - data的部分被植入executable code - 目標:使 stack 和其他 data area **Non-executable** - 變成OS中的standard - 但攻擊者用更精巧的方式攻擊 - **Write not Execute** 無法避免: - 只要 **Saved EIP** 指向已存在的code 此保障就無法阻止control transfer - **return-to-libc** 的攻擊基礎 - 複寫 Saved EIP 指向某 library routine - 編排 stack 看起來像 routine 的 argument - :table_tennis_paddle_and_ball: **ASLR Address Space Randomization** - attacker原本要預測targeted buffer的location 預測 return address - 目標:隨機擺放stack location使得預測困難 - 隨機擺放standard library routines - 用 `malloc` 跟把standard library routines放在heap ## Chapter 8: Access Control - :droplet: *定義* - 取得或終止requests的過程 1. 使用或獲得資訊或服務 2. 進入physical facilities - 根據security policy取得官方的准許以使用系統資源 - Function of Access Control - subject: 獲得資源的個體 eg. 人, processes, machines - object: 資源 eg. files, programs, processes - right: 如何使用 eg. read, write, execute - 越靠近application越複雜(complexity) - 越靠近硬體越可靠(reliability) - :apple: Application level - 較複雜且豐富的security policy - :apple: Middleware level - 如database, bookkeeping packages - 提供機制加強(enforce) access control - :apple: Operating System level - Middleware會用OS的資源 - files, programs, communication ports - :apple: Hardware level - processors, memory management software ### :cactus: Access Control Model - | Principle | Do operation | Reference monitor | Object [ACL] | | :------: |:-------:|:-------: | :-------: | | Source | Request | Guard | Resource | - Access Control包含 - **Authentication** priciple - **Authorization** determines who ### :cactus: Access Operations - :droplet: Example 1: only two access operations - **Observe:** 看object有什麼內容 - **Alter:** 修改object - :droplet: Example 2: **Bell-LaPadula Model** - **Execute** - **Append** 只寫不讀 - log files - **Write** 有讀 (observe和alter結合) ### :cactus: Type of Access Control - :droplet: *Discretionary(全權委託) Access Control (DAC)* - 定義一個**owner** - owner決定誰可以取得object或定義access right - :droplet: *Mandatory(強制性) Access Control (MAC)* - 一個 **system-wide policy** 規定object的access - :droplet: *Role Based Access Control(RBAC)* - 定義每個使用者(subject)的roles - :droplet: *Attribute Based Access Control(ABAC)* - 控制每個使用者(subject)相關的attributes - Access control的機制: - 認證使用者: password, Kerberos - 調解(Mediate)使用者對file, ports, processes的權限 ### :cactus: Access Control Matrix - $\text{A=a[o,s]}$ - | | file 1 | file 2 | | -------- | -------- | -------- | | proccess 1 | read, write, own | read | | proccess 2 | append | read, own | > Column = 資源 > Row = 使用者 > Entries = 權限 - 缺點: - subject跟object通常非常大量 - 通常entries是 - 空白的: 因為沒有權限 - 相同的: 因為預設 - 需要小心的storage management (creation/ deletion) ### :cactus: Access Control Lists - 儲存Access Control Matrix的每個 **Column** - 每個list: $\text{I=\{(s,r):s}\in S\text{,r}\subset R\text{\}}$ - example - $\text{acl(file1)={(process 1, {read,write,own}),(process 2,{append})}}$ - :droplet: Abbreviations(縮減) of ACLs - 將使用者分成不同的群組(classes) - example: Unix - owner, group, others - 但較不精準(loss of granularity) - 解決方法: - 允許定義所有access,但預設是compressed版本 - :droplet: Extended Permissions used in AIX - **Specify** 複寫(overwrite)原來的permissions - **Permit** 明確給定rights給使用者 - **Deny** 明確拒絕rights給使用者 - :droplet: Creation and Maintenance - 不同的實作取決於 - 哪些使用者可以修改ACL - root的存在 - 支援groups - 相反的權限 - 應用程式預設 - :droplet: Which subjects can modify ACL - Approach 1: - Creator - Unix - Approach 2: - anyone with paticular right - database management system R - 可以access table的人可以給別的user rights - :droplet: Do ACLs Apply to a Privileged user - 通常有限(limited fashion) - :droplet: Groups and Wildcards - 通常支援以簡化ACL - Group有兩個目的 - Refine使用者的性質 - 代表一群使用者 - Wildcards - $\text{(holly : * : r)}$ 表示 holly 可以 read 不管他在哪個group - $\text{(* : sys : r)}$ 表示 group ID sys 的可以 read - :droplet: Resolving conflicts - 一個ACL給同個使用者不同的權限 - 解法 - 若一個允許則允許 - 若一個拒絕則拒絕 - AIX - 套用第一個entry - Cisco - :droplet: Revocation of rights - 若被ownership控制 - 則owner決定revocation - 若被particular rights控制 - revocation較難 - 若A給B right,A要撤回 - 若B又給M right - 要紀錄grantor(給right的人)、timestamp - :droplet: **Capabilities** - Access Control Matrix的 **Row** - 使用者對所有檔案的權限的list - 創造新的object的使用者,要創造其他使用者的capabilities - 當呼叫其他使用者時,傳遞此capacity給他 - 缺點 - 難以overview - 難以revocation - OS要handle - 每個使用者都要追蹤自己的capability - :droplet: Authorization Table - ACL和capability的arbitrate(協調) | Subject | right | Object | | -------- | -------- | -------- | | A | own | file1 | |A|read|file1| |A|write|file1| |...|...|... | - sort subject可以得capability - sort object可以得ACL ### :cactus: Unix-based Systems - 所有Unix的file都用 **index node (inode)** 被OS管理 - inode定義file的屬性、權限和其他控制資訊 - **Directory(資料夾)** - 檔案名稱 - inodes的pointer - 每個object: `owner, group, others` - 權限: `rwx = read(4), write(2), execute(1)` - `d`: directory `-`: not - `chmod 754 filename` 對`filename`指定`rwx r-x r--` 權限 > 7=4+2+1 > 5=4+1 > 4=4 - User ID (uid) - Real user ID (ruid) - identify the owner - Effective user ID (euid) - 用在多數 access control - 可以被 system call 指定 (setuid) - Saved user ID (suid) - 前一個 user ID - Group ID (gid) - Assigning user ID - 若 process 是被 fork: 繼承三個user ID - 若被其他process執行,除非設 `set-user-ID` ,否則為新的 process的user ID - Dropping Privileges - 取得權限:指定一個 **privileged user ID** 到 `euid` - 丟棄: - 短暫: privileged user ID不存在 `euid` 但存在 `suid` - 永久:三個 user ID都不存 - :computer: `setuid` - 早期Unix只有這種 - 如果 `euid == 0`,設定`ruid` 及 `euid`為特定值 - 否則設`euid`為`ruid` $$\text{setuid(s)}=\begin{cases}\text{euid = ruid = s, if euid == 0}\\ \text{euid = s, otherwise}\end{cases}$$ - 缺點: 沒有上述的drop機制 - :comet: `seteuid` in System V - 可設定`euid`為任意user ID - 否則設`euid`為`ruid`或`suid` $$\text{seteuid(s)}=\begin{cases}\text{euid = s (any user ID), if euid == 0}\\ \text{euid = ruid / suid, otherwise}\end{cases}$$ - :baby_bottle: `setruid` in BSD - `ruid`和`euid`可以被設為任意user ID - 否則ruid或euid被設為另外一個 $$\text{setruid(s)}=\begin{cases}\text{euid = ruid = s (any user ID), if euid == 0}\\ \text{euid = ruid / ruid = euid, otherwise}\end{cases}$$ - :droplet: Inherited problem in modern system - 有些系統用 `setresuid`,可以設定三種user ID - 危險: - non-root user執行root權限,`suid==euid==0` - 攻擊者permanently drop root權限 - 新版`setuid`只允許drop `euid`不允許drop `suid` - :droplet: Extended Access Control List - Example: **FreeBSD** - 9 bits ACL: owner, group, others - 多一個特定權限: **named users/groups**,多3 bits - owner, named user, groups, others most closely matching one(最多符合)允許,則取得權限 ### :cactus: Role-based Access Control(RBAC) - 定義 **role** - 資源權限設給 role,使用者被分配不同的 role (根據responsibilities) - ![](https://i.imgur.com/nqxsVDl.png) - RBAC Access Matrix(多一個Role維度) | User\Role | R1 | R2 | | -------- | -------- | -------- | | U1 | X | | | U2 | X | | | U3 | | X | | Role\Object | R1 | R2 | | -------- | -------- | -------- | | R1 | control | | | R2 | | w | | R3 | Owner,r | | - :droplet: $\text{RBAC}_0,\text{RBAC}_1,\text{RBAC}_2,\text{RBAC}_3$ ![](https://i.imgur.com/kSzRCTV.png) - $\text{RBAC}_0$ - **User** - **Role** Job function - **Permission** 允許使用某資源 - **Session** 使用者和subset of roles對應到指定的使用者 - 使用者只跟需要的role建立session - **concept of least privilege** - $\text{RBAC}_1$ - 階層(Hierarchy) - subordinate(下屬) - $\text{RBAC}_2$ - Constraints - 定義mutually exclusive(獨家) roles - 限制cardinality of a role(role的人數) - $\text{RBAC}_3$ - $\text{RBAC}_1$ + $\text{RBAC}_2$ ### :cactus: Attribute-based Access Control - 用condition表示authorizations - eg. creator - 好處: - 彈性 - 有表達性(expressiveness) - 缺點: - 計算predicated(謂語)的performance影響 - web services/ cloud computing - :droplet: Attributes - Subject attributes - cause information/ change - Object attributes - passive - Environment attributes - environment or context - :droplet: Attribute Evaluation - ABAC仰賴計算attribute (subject/object given environment) - 精細

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully