Learning Journey is my way.
This is my personal study notes for whatever that I like the most in my life time.
(-)
are still works in progress.(el)
means external links.1 | MIT LICENSE. |
Started on 2017/11/22
]]>HTTP就是超文本傳輸協議(Hypertext Transfer Protocol),主要架構在TCP/IP之上的應用層,負責處理在Web上面客戶端(Client)和伺服端(Server)的之間的數據交換。在這裡,客戶端能發出一或多個請求(Request)給給伺服端, 而伺服端則會負責監聽(listen)與接受(accept)/拒絕(reject),對這些請求作出一或多個的回應(Ressponse)。
![]https://mdn.mozillademos.org/files/13679/Client-server-chain.png
除了客戶端和伺服端,他們之間也會有不同的代理proxies,也有着不一樣的作用。
Web Server可以服務並提供客戶端所請求的文檔。Server只是虛擬意義上代表一個機器:它可以是共享負載(負載均衡)的一組伺服器組成的計算機集群,也可以是一種複雜的軟件,通過向其他計算機(如緩存,資料庫伺服器,電子商務伺服器 …)發起請求來獲取部分或全部資源。
Server 不一定是一台機器,但一個機器上可以裝載的眾多Servers。
代理位於客戶端和伺服器之間,接收所有客戶端的HTTP請求,並把這些請求轉發給伺服器(可能會對請求進行修改之後轉發)。對用戶來說,這些應用程序就是一個代理,代表用戶訪問伺服器。代理的主要作用有過濾、屏蔽等.
文章系列分為六個部分。
Linux文件權限是用來管理所有用戶使用文件的程度。而設置權限的目的是為了方便管理者保護文件以及確保用戶只能使用自己有權限的文件。
文件的持有人。在預設下,文件的作者會是文件的擁有人也等同於使用者。
群組裡面可存在多個用戶。處於同一個群組裡面的所有用戶會具有相同的文件訪問權限。你可以把用戶加進同一個群組,然後再把文件權限交給此群組,這樣群裡的每個用戶都能有相同的訪問權限。
不屬於User和Group的使用者就是所謂的其他人。
ls -al
能用來查看文件的權限。
1 | [root@study ~]# ls -al |
當指令執行後,可以看到文件的屬性有7個欄位。下圖為7個欄位代表的意思。
d
為目錄(Directory)。-
為一般文件。l
為鏈接文件(Link file)。b
為區塊(block)文件, 儲存數據, 以提供系統隨機存取的介面設備。c
為字元(character)設備文件, 一些串列埠的介面設備, 例如鍵盤、滑鼠(一次性讀取裝置)。s
為數據介面文件(sockets), 通常被用在網路上的數據傳輸。f
為數據輸送文件(FIFO, pipe), 解決多個程序同時存取一個文件所造成的錯誤問題。接下來的字元中,以三個為一組,且均為『rwx』的三個參數的組合。
r
代表可讀(read)。w
代表可寫(write)。x
代表可執行(execute)。附錄:三個權限的位置不會改變,如果沒有權限,就會出現減號[ - ]作為代表。
不重要先跳過。
關於I-note的筆記
自我提醒需看Linux磁碟與檔案系統管理
常用指令有三個:
chmod
:改變文件權限chown
:改變文件擁有者chgrp
:改變文件所屬的群組Change access permissions, change mode.
格式如下:chmod [-cfvR] [--help] [--version] mode file
參數列表:
設置文字權限方式:
在設置權限時,你可以使用數字來代表不同的權限。權限的數字對照表如下:
例子
chmod 400 file
文件file只能讓Owner讀取。chmod 777 file
文件file能讓Owner,Group,以及Others讀取,寫入以及執行。 【7=4+2+1】這種方式比較容易一眼看的明白所設置的權限。
Operator的用途:
Operator | Description |
---|---|
+ | Adds a permission to a file or directory |
- | Removes the permission |
= | Sets the permission and overrides the permissions set earlier. |
例子
chmod a-x file
全部用戶不能執行file。chmod a+r file
全部用戶只能讀取file。chmod go+rw file
Others和Group可以讀取和寫入文件file。chmod u+x myscript.sh
只有Owner可以執行mycript.sh。chmod =rwx,g+s file
全部用戶都可以讀取,寫入和執行以及使用Group的ID。Change owner, change the user and/or group ownership of each given File to a new Owner.Chown can also change the ownership of a file to match the user/group of an existing reference file.
格式如下:
chown [Options] NewOwner File
chown [Options] Group File
chown [Options] reference=RFILE File
例子:
1 | [root@study ~]# chown [-R] 帳號名稱 檔案或目錄 |
Change group ownership.’chgrp’ changes the group ownership of each given File to Group (which can be either a group name or a numeric group id) or to match the same group as an existing reference file.
格式如下chgrp [Options] {Group | --reference=File} File
例子:
1 | 把initial-etup-ks.cfg 的群組改成users。 |
除了之前的rwx
權限,對於文件以及目錄還能用特殊權限來彌補之前三個權限的缺陷。特殊權限一共有3種:SUID(Set user ID),SGID (Set group ID)以及Sticky Bit。
SUID(Set owner User ID up on execution)通常用在程序執行時,給予用戶提供臨時的權限,以便用戶能使用該文件擁有者的權限去運行程序或文件。
SUID的基本限制與功能:
x
的權限。特殊權限的表示:
1 | $ ls -l /usr/bin/chsh /etc/passwd ←列出〝/usr/bin/chsh〞和〝/etc/passwd〞文件資訊。 |
更換SUID:
chmod 4755 filename
chmod g+s filename
SGID(Set Group ID up on execution)通常用在程序執行或者目錄時,給予用戶臨時權限,能讓該用戶為該群組的成員之一。此外,用戶也能使用擁有文件群組的權限來執行該程序。
SGID的基本限制與功能:
x
的權限。用在目錄上的功能:
r
與x
的權限時,該使用者能夠進入此目錄。w
的權限(可以新建文件),則使用者所建立的新文件的群組也會與此目錄的群組相同。特殊權限的表示:
1 | $ ls -l /usr/bin/wall |
更換SUID:
chmod 2750 filename
chmod g+s filename
應用在目錄的詳細例子:
在我的Linux系統裡面,擁有ning和yan這兩個帳號。這兩個帳戶都同時支持自己以及project
群組。現在我需要令到這兩個用戶需要共同擁有 /foryou/lovestory/ 目錄的開發權,且此目錄不能讓其他人進行查閱。
第一步:我會先設好這兩個帳戶的資料。
1 | [root@Milo ~]# groupadd project <==增加新的群組 |
第二步:建立目錄1
2
3[root@Milo ~]# mkdir /foryou/lovestory
[root@Milo ~]# ll -d /foryou/lovestory
drwxr-xr-x. 2 root root 12 March 18 00:22 /foryou/lovestory
第三步:開始設置SUID權限1
2
3
4[root@Milo ~]# chgrp project /foryou/lovestory
[root@Milo ~]# chmod 2770 /foryou/lovestory <== 在第一個位置那裡輸入其SGID代表數字2。
[root@Milo ~]# ll -d /foryou/lovestory
drwxrws---. 2 root project 12 March 18 00:25 /foryou/lovestory <==可以看到設置後2個帳戶都可以在此目錄建立新文件了。
目標: Linux File 權限
小目標:特殊權限
Sticky Bit
1.用在Owner對目錄有W,x權限時。
2.在該目錄建立文件或者目錄時,只有自己和Root才有權利
刪除該文件。
例子
Noel - 對於目錄A有群組和其他人的身份,且擁有對該目錄A的寫入權限。
他能對目錄內任何人建立的目錄以及文件均可進行刪除/換名或者搬遷等動作,但只要加了SBIT,Noel就只能對自己建立的檔案或目錄進行刪除/換名或者搬遷移動等動作,而無法刪除他人的檔案。
git help
git add
git push
git pull [options] [
git status
git show
git config –global user.name “Milo”
git config –global user.email “milo@gmail.com“
git clone https://gogojimmy@github.com/gogojimmy/Animal.git
origin/master
代表遠端數據庫「origin」的「master」分支位置。
origin/HEAD
代表遠端數據庫「origin」當前提交的位置。通常和「origin/master」的位置相同。
master
代表本地端數據庫的「master」分支位置。
git branch cat
gitk –all &
git checkout cat
git rebase
git log
git tag CatPrototype 027c483bd
今天我們來學一下怎樣分析一個ELF文件。xxx.o
在Linux裡面的文件格式是屬於可重定位文件(Relocatable File)
1 | /* SimpleSection.c */ |
Objdump工具可用來查看目標文件的結構和內容。在這裡我會先用-h
來看看這個ELF各個段的基本資訊。
輸入objdump -h SimpleSection.o
根據上圖我們可以知道一個ELF的可重定位文件可分為的段如下:
函數就是一段代碼裡面可重複使用的部分,我們在寫程式的時候常常都會遇到一些需要重用的功能,若將其功能寫成一個函數,那我們就不必要寫多一次該代碼,只需直接套用該函數就可以了。
1 | def 函數名(参數列表): |
比如說我們要生成一個有指定邊界的斐波那契數列的函數:
1 | >>> def fib(n): # write Fibonacci series up to n |
在上述的函數裡面,所有變量的賦值會存在局部符號表(Local Symbol Table)裡面。變量引用會先檢查局部符號表,接著就是包含函數的局部符號表,跟在後面是全局符號表,最後則是內置名字表。因此,全局變量是不能直接在函數裡面賦值(要用global語句來命名)。
一個函數定義會在當前的符號表裡面引入函數名字。而函數名字的值(函數體)會被Python的解釋器認為是用戶自定義的類型,之後可賦予其他的名字(變量名字以及被當作其他函數來使用。
比如說這樣:
1 | >>> fib |
現在我們就可以開始深入了解3種形式的函數使用方式。方式有這3種類型:
在Python裡面最常見的默認函數的形式多數含有一個或多個的實際參數,這使到該函數在被呼叫的時候可以使用更少已被定義的實際函數。我們來看看下面的例子:1
2
3
4
5
6
7
8
9
10
11def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
while True:
ok = input(prompt)
if ok in ('y', 'ye', 'yes'):
return True
if ok in ('n', 'no', 'nop', 'nope'):
return False
retries = retries - 1
if retries < 0:
raise OSError('uncooperative user')
print(complaint)
此函數的調用方式:
ask_ok('Do you really want to quit?')
ask_ok('OK to overwrite the file?', 2)
ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')
調用函數的時候,如果沒有傳遞參數,也會使用默認的參數。以下是沒有傳入參數的實際例子。1
2
3
4
5
6def printinfo(name,age = 24):
print("Name: ", name)
print("Age: ", age)
return
printinfo(age = 10,name="Bean Bean")
也可以把函數裡面的參數設定成某個固定的關鍵字來進行調用(Keyword = Value)。
例子:1
2
3
4
5def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")
在這例子裡面,可以接受一個必選參數 (voltage) 以及三個可選參數 (state, action, 和 type)。可以用以下任何一個方法來進行調用:1
2
3
4
5
6parrot(5000) # 1 positional argument
parrot(voltage=5000) # 1 keyword argument
parrot(voltage=5000000, action='VOOOOOM') # 2 keyword arguments
parrot(action='VOOOOOM', voltage=5000000) # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump') # 3 positional arguments
parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword
那麼無效的調用例子又是怎樣的呢?1
2
3
4parrot() # required argument missing
parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument
parrot(110, voltage=220) # duplicate value for the same argument
parrot(actor='John Cleese') # unknown keyword argument
另外,關鍵字的參數也必須跟隨在位置參數的後面。在傳遞期間,所有的關鍵字參數必須與函數可接受的某個參數互相匹配。而且任何参数都不可以多次赋值。下面的示例由于這種限制而無法呼叫該函數:
1 | >>> def function(a): |
在函數調用期間,關鍵字函數可以被使用來確定傳入的參數值。另外調用時候參數的順序與聲明時不一致也沒關係,因為Python解釋器會自動匹配相關參數值。
來看下這個程式:1
2
3
4
5
6
7
8
9
10
11#可以解釋函數
def printme(str):
"Print any entered String"
print (str);
return;
#调用printme函數
printme(str = "Pikachu is cute!");
結果
Pikachu is cute!
在你引入一個像**name
的參數時候,它會接收一個字典 Maping Types - dict。該字典包含了所有未出現在形式參數列表中的關鍵字參數。著
该字典包含了所有未出现在形式参数列表中的关键字参数。这里可能还会组合使用一个形如 name (下一小节详细介绍) 的形式参数,它接收一个元组(下一节中会详细介绍),包含了所有没有出现在形式参数列表中的参数值( name 必须在 **name 之前出现)。 例如,我们这样定义一个函数:
1 | def cheeseshop(kind, *arguments, **keywords): |
讓函數調用可變個數的參數。這些參數會被包裝進一個元組。
1 | def write_multiple_items(file, separator, *args): |
【暫時沒有用到】
http://www.runoob.com/python3/python3-function.html
http://docs.pythontab.com/python/python3.4/controlflow.html#tut-functions
虛擬內存是硬件異常,硬件地址翻譯,主存,磁盤文件和內核軟件完美的交互,它為每個進程提供了一個大的,一致且私有的空間。它具備了3個非常重要的能力:
malloc函數是C/C++語言裡面用來管理內存的函數。在中文裡面稱為動態內存分配(memory allocation)。它的格式是長這個樣子的:1
void* malloc(size_t size);.//size_t 是你想定義的size的種類,例如Int。而size則是你想設置使用多少Byte的內存。
這個函數要實現的功能就是分配一段可連續使用的內存在系統裡面,但必須具備以下的要求:
想看malloc命令可以在Terminal輸入這個指令1
man malloc
每個進程有2^N字節的內存,N是機器位數。比如以64位元的操作系統來說的話,每個進程的虛擬地址空間為2^64Byte。
這種虛擬地址空間的作用:簡化程序編寫+方便操作系統對進程的內存進行隔離管理。在Linux裡面
PWN知識全制霸這系列是為了教導大家如何從一個PWN萌新成為佼佼者那樣的大佬。那麼是什麼是PWN呢?PWN就是利用各種漏洞攻擊系統主機從而獲得系統管理員的權限。
而Part 1就是一些你們得懂的匯編基本和常用到的知識。
本文參考:王爽-匯編語言第三版 & 小信豬原始部落的學習筆記
機械語言是機械指令的集合。
例子指令: 01010000 (PUSH AX)
左部分為機械語言括號裡面則是所謂的匯編語言。
匯編語言就是能在硬件上直接工作的編程語言。而匯編語言的出現是為了讓人們用容易理解的方式去表達出機器指令代表的意思。雖然電腦只能讀懂0和1,然而,通過編譯器,我們輸入的匯編語言最終會轉譯成電腦所理解的機械語言。
由3種匯編指令:匯編指令,偽指令和其他符號。
也就是平常大家所說的內存,用來存放指令和需要運算的數據。
存儲器能被劃分成幾個單元,每個存儲器單元從0開始順序編號,如一個存儲器有128個存儲單元,編號從0到127微型機存儲器的存儲單元可以存儲一個Byte(1位元組=8bit,即8個二進位)。含有128個存儲單元的存儲器可以存儲128個Byte。
二進位制是由0和1組成。
大端模式 Big Endian:低位放低位地址,高位放到高位地址。
低地址 ——– 高地址 (比如存放0x01234567)0x01 0x02 0x03 0x04 0x05 0x06 0x07
小端模式 Small Endian:低位放高地址,高位放低地址
低地址 ——– 高地址 (比如存放0x01234567)0x07 0x06 0x05 0x04 0x03 0x02 0x01
CPU要從讀寫數據的需要知道存儲單元所在的地址,到底指明的是哪一個存儲器,進行怎樣的操作。而它會和電腦裡面的芯片進行以下3種的信息交互。
1.CPU透過地址線發出地址訊息3。
2.CPU通過控制線發出記憶體讀命令,選中存儲器晶片,並通知它,將要從中讀取數據。
3.存儲器將3號單元中的數據8通過傳輸線送入CPU。
1.CPU透過地址線發出地址訊息3。
2.CPU通過控制線發出記憶體命令,選中存儲器晶片,並通知它,要想其中寫入數據。
3.CPU透過傳輸線將數據26送入記憶體的3號單元中。
CPU通過地址總線來指定存儲器單元。地址總線上能傳送多少個不同的信息,CPU就可以對多少個存儲單元進行尋址。
一個CPU有N根地址線,則可以說這個CPU的地址總線的寬度為N。這樣的CPU最多可以尋找 $ \ 2^N \ $ 個內存單元.
決定了CPU的尋址能力。
CPU與內存或其他器件之間的數據傳送是通過數據總線來進行的。數據總線的寬度決定了CPU和外界的數據傳送速度。8根數據總線一次可傳送一個8位二進制數據(即一個字節)。16根數據總線一次可以傳送兩個字節,32的話就是4個字節,最後,64就會是8個字節了。
決定了CPU與其他器件進行數據傳送時的一次數據傳送量。
CPU對外部器件的控制是通過控制總線來進行的。在這裏控制總線是一個總稱,控制總線是一些不同控制線的集合。有多少個控制總線,就意味着CPU提供了對外部器件的多少種控制。所以,控制總線的寬度決定了CPU對外部器件的控制能力。
決定了CPU對系統中其他器件的控制能力
舉例來說,一個CPU的地址總線寬度為10,那麼可以尋址$ \ 2^10 = 1024\ $個內存單元,這1024個可尋到的內存單元就構成這個CPU的內存地址空間。
在CPU裡面,寄存器的作用是用來暫存指令、數據和位址。它們分別是:
1 | 64-bit register | Lower 32 bits | Lower 16 bits | Lower 8 bits |
http://slideplayer.com/slide/4194257/14/images/11/Register+Layout+RAX+EAX+AX+AH+AL.jpg
EAX:称为累加器,常用于算数运算、布尔操作、逻辑操作、返回函数结果等。
EBX:称为基地址寄存器,常用于存档内存地址。
ECX:称为计数寄存器,常用于存放循环语句的循环次数,字符串操作中也会常用。
EDX:称为数据寄存器,常常和EAX一起使用。
对于寄存器%eax、%ebx、%ecx和%edx,各自可作为两个独立的16位寄存器使用,而低16位寄存器还可继续分为两个独立的8位寄存器使用。
注意:
上面所述的4个通用寄存器的专门用途不是一成不变的,编译器在编译程序的时候会根据很多因素,例如编译器、编译条件、操作系统等做出相应的改变,读者要知道着手研究的程序是用什么编译器编译,然后针对具体的编译器参考该编译器的说明。
EIP(Instruction Pointer):是指令寄存器,指向处理器下条等待执行的指令地址(代码段内的偏移量),每次执行完相应汇编指令EIP值就会增加。
ESP(Stack Pointer):是栈指针寄存器,存放执行函数对应栈帧的栈顶地址(也是系统栈的顶部),永遠指向栈区域的栈顶位置。
EBP(Base Pointer):是扩展基址指针寄存器,存放执行函数对应栈帧的栈底地址,用于C运行库访问栈中的局部变量和参数。
变址寄存器:顾名思义,变址的含义是内存地址会变动,也就是说变址寄存器中存放在变动的内存地址。80386架构中有两个变址寄存器,分别为ESI和EDI。
用途:ESI和EDI通常用来配合使用完成数据的赋值操作,下面是一个EIS和EDI配合使用的例子。
Rep movs dword ptr [edi],dword ptr [esi]
上面的指令把ESI所指向的内存地址中的内容复制到EDI所指向的内存中,数据的长度在ECX寄存器中指定。
The word ‘Sturcture’ here means how the files and folders are organized in the file system. What are the most important files should put in your project and why you need them. By understand this, you may find the best way to organise your codes and other related files effectively.
In this section, I will going to show some of the point you can concern when you are structing your project.
Repository is the first thing you need to concern. When other people see your repository’s page they need to understand what is your project about and how to use it and so on. Hence, you should put a “README” file in your repository to help others understand your project better. Usually, “README” should also include enough details to help a new user get started, e.g. how to compile, how to install, and how to start integrating.
A README is a text file that introduces and explains a project. It contains information that is commonly required to understand what the project is about.
A good readme file for your project can have the following informations:
One thing you should remember, it is not nessecry to inlude all the above information in your “README”. As longs as you can point out the main things that a user should know about project is enough, for the rest of the full details information you can put under your documentation or wiki.
Here are some guideline as well for writing a good “README”.
Next, I will give an example of a python project repository.
1 | README.rst |
Purpose: code of intrest. The source code that you use in your project.
setup.py
is a python file, which usually tells you that the module/package you are about to install has been packaged and distributed with Distutils, which is the standard for distributing Python Modules. For more details, you can check here
A pip requirements file should be placed at the root of the repository. It should specify the dependencies required to contribute to the project: testing, building, and generating documentation.
If your project has no development dependencies, or you prefer development environment setup via setup.py, this file may be unnecessary.
This is the place to put your documentation of your project.
Purpose: Package integration and unit tests.
Starting out, a small test suite will often exist in a single file:
./test_sample.py
Once a test suite grows, you can move your tests to a directory, like so:
tests/test_basic.py
tests/test_advanced.py
In order to prevent keep importing the pakage modules whenever you are doing a testing, you can do it in this way.
Create a file call tests/context.py
. This file allows you to modify the path for resolving the packaging issue.
1 | import os |
Fianally, what you need to do is just add one line in each of your test.py. After that you can skip install the dependencies or pakage modules.from .context import sample
Purpose: Defining generic tasks for your project.
A good makefile allow you to define the rules for your python file like which file need to pre-compile, recompile or even you can execute the shell script by using a makefile. The best part of using a makefile is to automate your code running. Once you done making your makefile, you only need to use the make command and easily run tests on your project.
Sample of Python makefile
1 | .PHONY: test upload clean bootstrap |
Learn more about makefile.
To be continue
]]>GDB是在Linux裡面用來調試C/C++程序的強大工具。而它主要的用途如下。
• Start your program, specifying anything that might affect its behavior.
• Make your program stop on specifed conditions.
• Examine what has happened, when your program has stopped.
• Change things in your program, so you can experiment with correcting the effects of one bug and go on to learn about another.
在Terminal输入gdb
進入GDB的環境後就可以用file <program名字>
來開始調試你程序(program)。
有3種啟動的方式。
gdb <program>
program是你的當前要執行的文件,一般在你現在所處於的目錄下
gdb <program> core
用gdb同時調試一個運行中的程序以及core文件。
gdb <program> <PID>
此外,你也可以指定GDB去調試運行中程序的Process ID。
-s <program>
:讀取program的符號表(Symbol Table)。-e <program>
:用program作为可執行的文件来執行,或者在和core dump連接的時候用来檢查出數據-c <program>
:用program作為core dump。-p <program>
:配合attach
指令,來連接PID的號碼。-x <program>
:從program裡面執行GDB的指令-ex command
:執行單一的GDB指令 例子:gdb -ex ’target sim’
list
list <linenum>
list function
list -
set listsize count
set listsize unlimited
1 | 基本使用 break <location>,以下是可以用的location。 |
1 | 基本使用 info <想看的資訊> |
GDB中使用“x”命令来打印内存的值,格式为x/nfu addr
。其意思為以f格式打印從addr開始的n个長度單元為u的內存值。參數具體含義如下:
1 | Example 1:打印16個在地址a以16進位表示且大小為byte數值 |
disass
ni - next instruction
• si - step into
• backtrace - 顯⽰上層所有 stack frame 的資訊
• continue
set address=value
• 將 address 中的值設成 value ⼀次設 4 byte
• 可將 換成 {char/short/long} 分別設定 1/2/8 byte
• e.g.
• set *0x602040=0xdeadbeef
• set {int}0x602040=1337
在有debug symbol下
• list : 列出 source code
• b 可直接接⾏號斷點
• info local : 列出區域變數
• print val : 印出變數 val 的值
attach pid : attach ⼀個正在運⾏的 process
• 可以配合 ncat 進⾏ exploit 的 debug
• ncat -ve ./a.out -kl 8888
• echo 0 > /proc/sys/kernel/yama/ptrace_scope
預備文件:hello.c1
2
3
4
5
6
int main(void)
{
printf("Hello, world!\n");
return 0;
}
編譯gcc -g hello.c -o hello
後就開始用GDB來調試。
/m
When this option is specified, the disassemble command will show the source lines that correspond to the disassembled instructions.
/r
When this option is specified, the disassemble command will show the raw byte values of all disassembled instructions.
disass 0x4004ef,0x4004f9
http://wiki.ubuntu.org.cn/%E7%94%A8GDB%E8%B0%83%E8%AF%95%E7%A8%8B%E5%BA%8F
https://deepzz.com/post/gdb-debug.html
深入理解計算機第三章筆記1
2
3
4
5
6
7multstore:
pushq %rbx
movq %rdx,%rbx
call mult2
movq %rax,(%rbx)
popq %rbx
ret
匯編代碼解釋pushq %rbx
將寄存器rbx的內容放入程序棧
objdump -d mstore.o
可查看機械代碼文件內容
代碼範例21
2
3
4
5
6
7
8
9
10
11
12
13#include <stdio.h>
void multstore(long,long,long *);
int main(){
long d;
mulrstore(2,3, %d);
printf("2 *3 --> %ld\n",d);
return 0;
}
long mult2(long a,long b){
long s = a * b;
return s;
}
gcc -Og -o prog main.c mstore.c
2大規則For生成小於8字節結果的指令:
生成1字節和2字節的指令會保持,剩下的字節不會改變。
生成4字節數字的指令會把高位4個字節變0.
RSP - 指明棧運行時結束位置。
1.立即數(Immediate) - $ + 整數 例子$-577 /$0x1F等等
2.寄存器 - RAX,RBX,RCX…RIP等等 ra表示任意寄存器a,而R[ra]表示它的值,看成一個數組R,用寄存器標識符作為索引。
3.內存引用 - 用Mb[Addr]表示對儲存在內存裡面。
答案
|操作數|值|解釋|
|:——|:——|:——|
|%rax|0x100|寄存器|
|0x104|0xAB|絕對地址|
|$0x108|0x108|立即數|
|(%rax)|0xFF|間接尋址:因為這裡說的是去尋找0x100地址的值|
|4(%rax)|0xAB|間接尋址:因為這裡說的是去尋找0x104地址的值|
|9(%rax,%rdx)|0x11|0100+0003+0009=0x10C,答案為地址0x10C的值|
|260(%rcx,%rdx)|0x13|0001+0003+0104=0x108,答案為地址0x108的值,260要轉成16進制才可以進行運算|
|0xFC(,%rcx,4)|0xFF|0004+00FC=0xFF, 0004是0001經過比例4後變成的|
|(%rax,%rdx,4)|0x11|000C+0100=0x10C,000C是0003經過比例4=>3x4=12=C變成的|
mov S,D- 把數據從源位置S傳送到目標位置D。
1.將較小的源值複製到較大的目的時使用MOVZ或MOVS。
2.MOVZ把目的中的字節填0
3.MOVS把指令通過符號擴展來填充,同時把源操作的最高位進行複製
4.每個指令最後2個字符是大小指示符號。第一個指定源的大小,後者指定第二個明目的大小
【上述指令以內存地址為來源,以寄存器作為目的】
movabsq $0x0011223344556677,%rax %rax=0011223344556677
movb $-1,%al %rax=00112233445566FF
movw $-1,%ax %rax=001122334455FFFF
movl $-1,%eax %rax=00000000FFFFFFFF
movq $-1,%rax %rax=FFFFFFFFFFFFFFFF
練習3.2
movl %eax,(%rsp) 雙字,因為EAX是32位元(雙字)寄存器
movw (%rax),%dx 字,因為dx是16位元寄存器
movb $0XFF,%bl 字節,因為bl是8位元寄存器
movb (%rsp,%rdx,4).%dl 字節,因為dl是8位元寄存器
movq (%rdx),(%rax) 四字,因為RAX為64位元寄存器
movw %dx,(%rax) 字,因為dx是16位元寄存器
下面是movb,movsbq和movzbq在傳送上改變/不改變高字節的差別1
2
3
4movabsq $0x001122334455677,%rax %rax = 0011223344556677
movb $0xAA,%dl %dl = AA
movb $dl,%al %rax = 00112233445566AA
movsbq $dl,%rax %rax = FFFFFFFFFFFFFFAA
用來保存一系列有序項目的集合。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# 訪問列表中的值
list1 = ['Google', 'Youtube', 2017, 2018]
list2 = [1, 2, 3, 4, 5, 6, 7 ]
print("list1[0]: ", list1[0])
print("list2[1:5]: ", list2[1:5])
# 更新列表內容
list = ['Google', 'Youtube', 2017, 2018]
print("The 3rd Element is ".list[2])
list = [2] = 2020
print("The New 3rd Element is ",list[2])
# 刪除列表內容
list = ['Google', 'Runoob', 1997, 2000]
print (list)
del list[2]
print ('删除第三个元素 : ', list)
len(list)
- 列表裡面元素的數量。max(list)
- 返回列表元素最大值。min(list)
- 返回列表元素最小值。list(seq)
- 將元組轉為列表。
list.append(obj)
- 在列表末尾添加新的對象。
使用例子1
2
3
4
5
6list1 = ['Google', 'Facebook', 'Twitter']
list1.append('Instagram')
print ("更新后的列表 : ", list1)
結果
更新后的列表 : ['Google', 'Facebook', 'Twitter', 'Instagram']
list.count(obj)
- 統計某個元素在列表中出現的次數。
使用例子1
2
3
4
5
6aList = ['Google', 'Instagram','Facebook', 'Twitter', 'Instagram']
print ("Instagram元素個數 : ", aList.count('Instagram'))
結果
Instagram元素個數 : 2
list.extend(seq)
- 在列表末尾一次性追加另一個序列中的多個值(用新列表擴展原來的列表)。
使用例子1
2
3
4
5
6
7list1 = ['Google', 'Instagram','Facebook']
list2=list(range(5)) # 创建 0-4 的列表
list1.extend(list2) # 扩展列表
print ("擴展後的列表:", list1)
結果
擴展後的列表:['Google', 'Instagram','Facebook', 0, 1, 2, 3, 4]
list.pop(obj=list[-1])
- 移除列表中的一個元素
使用例子1
2
3
4
5
6
7
8
9list1 = ['Google','Instagram','Facebook']
list1.pop()
print ("列表現在為 : ", list1)
list1.pop(1)
print ("列表現在為 : ", list1)
結果
列表現在為 : ['Google', 'Instagram','Facebook']
列表現在為 : ['Google']
list.remove(obj)
- 用於移除列表中某個值的第一個匹配項。
使用例子1
2
3
4
5
6
7
8
9list1 = ['Google','Instagram','Facebook', 'Twitter']
list1.remove('Facbook')
print ("列表現在為 : ", list1)
list1.remove('Google')
print ("列表現在為 : ", list1)
結果
列表現在為 : ['Google', 'Instagram', 'Twitter']
列表現在為 : ['Instagram', 'Twitter']
list.reverse((obj)
- 反向列表中元素。
使用例子1
2
3
4
5
6list1 = ['Google', 'Facebook', 'Taobao', 'Baidu']
list1.reverse()
print ("列表反轉後: ", list1)
結果
列表反轉後: ['Baidu', 'Taobao', 'Facebook', 'Google']
list.sort([func])
- 對原列表進行排序,如果指定參數,則使用比較函數指定的比較函數。
使用例子1
2
3
4
5
6list1 = ['Google', 'Runoob', 'Taobao', 'Baidu']
list1.sort()
print ("列表排序后: ", list1)
結果
列表排序后: ['Baidu', 'Google', 'Runoob', 'Taobao']
list.clear()
- 清空列表內容。
使用例子1
2
3
4
5
6list1 = ['Google', 'Runoob', 'Taobao', 'Baidu']
list1.clear()
print ("列表清空后: ", list1)
結果
列表清空后: [ ]
list.copy()
- 複製列表
使用例子1
2
3
4
5
6list1 = ['Google', 'Runoob', 'Taobao', 'Baidu']
list2 = list1.copy()
print ("list2 列表: ", list2)
結果
list2 列表: ['Google', 'Runoob', 'Taobao', 'Baidu']
list.index(obj)
- 從列表中找出某個值第一個匹配項的索引位置。
1 | list1 = ['Google', 'Runoob', 'Taobao','Twitter'] |
list.insert(index,obj)
- 將指定對象插入列表的指定位置。
1 | list1 = ['Google', 'Yahoo', 'Instargram'] |
用來保存一系列有序項目的集合,只是裡面的內容無法更改。
1 | # 一般使用方法 |
屬於Associative arrays。字典是由键值(Keys)與數值(Values)組成。格式是這樣的d = {key1 : value1, key2 : value2 }
。其儲存方式為無序。
key的規則:不可以重複出現。例子若出現重複情況,python只會記住最新賦予的數值。
使用例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39dict = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
# 訪問裡面的數值
dict = {'Name': 'Milo','Age': 24, 'Class': 'First'}
print ("dict['Name']: ", dict['Name'])
print ("dict['Age']: ", dict['Age'])
結果
dict['Name']: Milo
dict['Age']: 24
# 修改字典裡面的內容
dict = {'Name': 'Milo', 'Age': 24, 'Class': 'First'}
dict['Age'] = 8 # 更新年齡
dict['School'] = "W3School" # 加新的信息
print ("dict['Age']: ", dict['Age'])
print ("dict['School']: ", dict['School'])
結果
dict['Age']: 8
dict['School']: W3School
dict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
# 刪除自動字典裡面的內容
del dict['Name'] # 删除键 'Name'
dict.clear() # 清空字典
del dict # 删除字典
print ("dict['Age']: ", dict['Age'])
print ("dict['School']: ", dict['School'])
結果
Traceback (most recent call last):
File "test.py", line 9, in <module>
print ("dict['Age']: ", dict['Age'])
TypeError: 'type' object is not subscriptable
<class 'dict'>
用來刪除字典裡面的所有元素
1
2
3
4
5
6
7
8dict = {'Name': 'Milo', 'Age': 24, 'Class': 'First'}
print ("字典長度 : %d" % len(dict))
dict.clear()
print ("字典删除后長度 : %d" % len(dict))
結果
字典长度 : 3
字典删除后長度 : 0
用来返回字典的浅複製。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19dict1 = {'user':'Milo','num':[1,2,3]}
dict2 = dict1
dict3 = dict1.copy() # 深Copy父對象(一級目錄),子對象(二級目錄)不copy。
# 修改data數據
dict1['user']='root'
dict1['num'].remove(1)
# 输出結果
print(dict1)
print(dict2)
print(dict3)
結果
{'user': 'root', 'num': [2, 3]}
{'user': 'root', 'num': [2, 3]}
{'user': 'Milo', 'num': [2, 3]}
# dict3的父對象進行了深Copy,因此不會隨著dict1修改而修改,子对象是浅copy會随dict1的修改而修改。
創建一個新的字典,以序列seq中元素做字典的鍵,value為字典所有鍵對應的初始值。格式如下:dict.fromkeys(seq[, value]))
1 | seq = ('name', 'age', 'book') |
返回指定鍵的值,如果值不在字典中返回default值。dict.get(key, default=None)
1 | dict = {'Name': 'Milo', 'Age': 24} |
查看字典裡面是否存在某個鍵。1
2
3
4
5
6dict = {'Name': 'Milo', 'Age': 24}
if 'Age' in dict:
print ("鍵Age存在"))
結果
鍵Age存在
返回一切字典裡面的Key和Value。1
2
3
4
5dict = {'Name': 'Milo', 'Age': 24}
print ("Value : %s" % dict.items())
結果
Value : dict_items([('Age', 24), ('Name', 'Milo')])
返回字典裡面所有的Key。1
2
3
4
5dict = {'Name': 'Milo', 'Age': 24}
print ("字典裡面所有的鍵為: %s" % dict.keys())
結果
字典裡面所有的鍵為: dict_keys[('Age','Name')])
如果Key在字典裡面,返回Defaut的Key以及其對應的Value,反之則新的Key的默認值None。
1 | dict = {'Name': 'Milo', 'Age': 24} |
把dict2的值更新到dict裡面。
1 | dict = {'Name': 'Milo', 'Age': 24} |
返回所有在字典裡面的值
1 | dict = {'Name': 'Milo', 'Age': 24,'Hobby': 'Diabolo'} |
用來刪除字典給固定的鍵key所對應的值,返回的值是被刪除的值,因此必須給key,否則返回的會是Default的值。
1 | 'name': '量子城', 'post': 25, 'url': 'http://diabolo94.github.io/'} site= { |
隨機返回並且刪除字典裡中的一對Key和Value,通常刪除最後的那一Pair。
1 | site= {'name': '量子城', 'post': 25, 'url': 'http://diabolo94.github.io/'} |
關於集合以後補上。
]]>特殊符號 | 說明 |
---|---|
. | 匹配除换行符(Newline)以外的任意字符 |
^ | 匹配字符串的開始 |
$ | 匹配字符串的結束 |
* | 匹配前面出現0次或多次的正則表達式 |
+ | 匹配前面出現1次或多次的正則表達式 |
? | 匹配前面出現0次或1次的正則表達式 |
{m} | m必須為一個非負整數。匹配確定的m次,例如可以匹配a{6},你只能匹配有6個’a’的正則式 |
{m,n} | 匹配的次數需要在m和之間。其中m<=n.例如,o{1,3}只可以匹配“fooooood”裡面前三個的o。 |
{m,} | 匹配的次數最少為m,最多無限制。 |
{m,n}? | 加了問號正則式只會匹配m而已,例子:‘aaaaaa’中,a{3,5}?,只會匹配3個a。 |
\ Either escapes special characters (permitting you to match characters like ‘*’, ‘?’, and so forth), or signals a special sequence; special sequences are discussed below.
If you’re not using a raw string to express the pattern, remember that Python also uses the backslash as an escape sequence in string literals; if the escape sequence isn’t recognized by Python’s parser, the backslash and subsequent character are included in the resulting string. However, if Python would recognize the resulting sequence, the backslash should be repeated twice. This is complicated and hard to understand, so it’s highly recommended that you use raw strings for all but the simplest expressions.
[] Used to indicate a set of characters. In a set:
Characters can be listed individually, e.g. [amk] will match ‘a’, ‘m’, or ‘k’.
Ranges of characters can be indicated by giving two characters and separating them by a ‘-‘, for example [a-z] will match any lowercase ASCII letter, [0-5][0-9] will match all the two-digits numbers from 00 to 59, and [0-9A-Fa-f] will match any hexadecimal digit. If - is escaped (e.g. [a-z]) or if it’s placed as the first or last character (e.g. [-a] or [a-]), it will match a literal ‘-‘.
Special characters lose their special meaning inside sets. For example, [(+)] will match any of the literal characters ‘(‘, ‘+’, ‘‘, or ‘)’.
Character classes such as \w or \S (defined below) are also accepted inside a set, although the characters they match depends on whether ASCII or LOCALE mode is in force.
Characters that are not within a range can be matched by complementing the set. If the first character of the set is ‘^’, all the characters that are not in the set will be matched. For example, 5 will match any character except ‘5’, and [^^] will match any character except ‘^’. ^ has no special meaning if it’s not the first character in the set.
To match a literal ‘]’ inside a set, precede it with a backslash, or place it at the beginning of the set. For example, both [()[]{}] and [{}] will both match a parenthesis.
| A|B, where A and B can be arbitrary REs, creates a regular expression that will match either A or B. An arbitrary number of REs can be separated by the ‘|’ in this way. This can be used inside groups (see below) as well. As the target string is scanned, REs separated by ‘|’ are tried from left to right. When one pattern completely matches, that branch is accepted. This means that once A matches, B will not be tested further, even if it would produce a longer overall match. In other words, the ‘|’ operator is never greedy. To match a literal ‘|’, use |, or enclose it inside a character class, as in [|].
To be continue.
]]>鏈接就是將不一樣部分的代碼和數據收集,然後再合成一個單一的文件,該文件可以被載入到內存並且被執行。鏈接可以在編譯時、載入時或運行時執行。
本文章涵蓋的內容有目標文件種類、ELF格式、PLT(Procedure Linkage Table,程序鏈接表)、GOT(Global Offset Table,全局偏移表)、靜態鏈接、載入時和運行時的動態鏈接。
在了解鏈接的過程之前,我們必須先對ELF格式和目標文件有個概念才能更加容易對鏈接有深刻的理解。
目標文件是源代碼編譯後,但未進行鏈接的那些中間文件(Windows裡面是.obj,Linux裡面是.o),也可以說是位元組塊的集合。而連結器的作用就是要將這些元組塊連接起來,確定被連結塊的運行時位置,並修改代碼和數據塊中的各種位置。
目標文件的三種形式為:
目标文件由匯編器和鏈接器創建,是可以在处理器上直接運行的二进制程序。那些需要虛擬機才能够執行的程序,如shell脚本,並不属于这一范围。
而以上三種形式在Linux裡面都主要稱為ELF文件格式,因為ELF其實本身就是程序的載體,只要通過編譯後的代碼,最終都會被轉成ELF文件格式然後再讓系統根據所定義出來的ELF格式文件來進行所謂的靜態鏈接或動態鏈接(待查證)。
那麼一個ELF文件是由以下幾個部分所組成:
英文版本的Elf文件格式
當然ELF文件一般會看成這2種視角。
Elf頭部用來描述文件的基本屬性。例如:目標機器型號,程序入口地址和ELF文件版本等等。
ELF文件頭結構以及裡面的相關常數會被定義在/usr/include/elf.h
裡面。這裡是elf.h的內容。
在elf.h
裡面ELF文件頭的定義部分是這樣的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47/* The ELF file header. This appears at the start of every ELF file. */
#define EI_NIDENT (16)
/*32位的版本*/
typedef struct
{
unsigned chare_ident[EI_NIDENT];/* Magic number and other info */
Elf32_Halfe_type;/* Object file type */
Elf32_Halfe_machine;/* Architecture */
Elf32_Worde_version;/* Object file version */
Elf32_Addre_entry;/* Entry point virtual address */
Elf32_Off e_phoff;/* Program header table file offset */
Elf32_Off e_shoff;/* Section header table file offset */
Elf32_Worde_flags;/* Processor-specific flags */
Elf32_Halfe_ehsize;/* ELF header size in bytes */
Elf32_Halfe_phentsize;/* Program header table entry size */
Elf32_Halfe_phnum;/* Program header table entry count */
Elf32_Halfe_shentsize;/* Section header table entry size */
Elf32_Halfe_shnum;/* Section header table entry count */
Elf32_Halfe_shstrndx;/* Section header string table index */
} Elf32_Ehdr;
/*64位的版本*/
typedef struct
{
unsigned chare_ident[EI_NIDENT];/* Magic number and other info */
Elf64_Halfe_type;/* Object file type */
Elf64_Halfe_machine;/* Architecture */
Elf64_Worde_version;/* Object file version */
Elf64_Addre_entry;/* Entry point virtual address */
Elf64_Off e_phoff;/* Program header table file offset */
Elf64_Off e_shoff;/* Section header table file offset */
Elf64_Worde_flags;/* Processor-specific flags */
Elf64_Halfe_ehsize;/* ELF header size in bytes */
Elf64_Halfe_phentsize;/* Program header table entry size */
Elf64_Halfe_phnum;/* Program header table entry count */
Elf64_Halfe_shentsize;/* Section header table entry size */
Elf64_Halfe_shnum;/* Section header table entry count */
Elf64_Halfe_shstrndx;/* Section header string table index */
} Elf64_Ehdr;
/* Fields in the e_ident array. The EI_* macros are indices into the
array. The macros under each EI_* macro are the values the byte
may have. */
以下是ELF頭的例子。
而我用來查看SimpleSection.o
的Elf頭。源文件代碼如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19/* SimpleSection.c */
int printf(const char* format,...);
int global_init_var =84; //
int global_uninit_var;
void func1(int i)
{
printf("%d\n",i);
}
int main(void)
{
static int static_var =85;
static int static_var2;
int a = 1;
int b;
funcl1(static_var + static_var2 + a + b);
}
然後用gcc -c SimpleSection.c
後你會得到一個SimpleSection.o的二進制文件,這時你就可以用readelf -h SimpleSection.o
來查看Elf頭。這裡 -c 的意思為不進行鏈接。
e_ident
主要是用來判定該文件為ELF目標文件,同時提供關於用於解碼和解釋文件結構有關的數據表示方式(Data Representation of a data structure)。這個數組對於不同的下標的含義如下:
宏名稱 | 取值 | 目的 |
---|---|---|
EI_MAG0 | 0 | 文件標識(File identification) |
EI_MAG1 | 1 | 文件標識(File identification) |
EI_MAG2 | 2 | 文件標識(File identification) |
EI_MAG3 | 3 | 文件標識(File identification) |
EI_CLASS | 4 | 文件類別(File Class) |
EI_DATA | 5 | 數據編碼(Data Encoding) |
EI_VERSION | 6 | 文件版本(File Version) |
EI_OSABI | 7 | OS/ABI 標識(OS/ABI) |
EI_ABIVERSION | 8 | ABI版本 |
EI_PAD | 9 | 補齊字節開始處(Start of padding bytes) |
EI_NIDENT | 16 | e_ident部分的大小(Size of e-ident[]) |
其中EI_MAG0
到EI_MAG3
會顯示出這個文件是ELF文件,也叫做魔數(Magic Number)。
名稱 | 值 | 位置 |
---|---|---|
ELFMAG0 | 0x7f | e_ident[EI_MAG0] |
ELFMAG1 | ‘E’ | e_ident[EI_MAG1] |
ELFMAG2 | ‘L’ | e_ident[EI_MAG2] |
ELFMAG3 | ‘F’ | e_ident[EI_MAG3] |
e_ident[EI_CLASS]
為e_ident[EI_MAG3]
的下一个字節,專用來表示文件的類型或容量。
名稱 | 值 | 意義 |
---|---|---|
ELFCLASSNONE | 0 | 無效類型 |
ELFCLASS32 | 1 | 32位文件 |
ELFCLASS64 | 2 | 64位文件 |
這兩個類型的差別在於ELFCLASS32類型支持文件大小和虚拟地址空間上限为4GB的機器而ELFCLASS64類型被保留用于64位架構。它表明目標文件能会改變。在必要时,会定義附带有不同的基本類型目標文件數據大小的其他類型。
e_ident[EI_DATA]
位元組給出了目標文件中的特定處理器數據的編碼方式。下面是目前已定義的編碼:
名稱 | 值 | 意義 |
---|---|---|
ELFDATANONE | 0 | 無效數據編碼 |
ELFDATA2LSB | 1 | 小端 |
ELFDATA2MSB | 2 | 大端 |
大端模式,是指數據的高位元組保存在記憶體的低地址中,而數據的低位元組保存在記憶體的高地址中,這樣的存儲模式有點類似於把數據當作字串順序處理:地址由小向大增加,而數據從高位往低位放;這和我們的閱讀習慣一致。
小端模式,是指數據的高位元組保存在記憶體的高地址中,而數據的低位元組保存在記憶體的低地址中,這種存儲模式將地址的高低和數據位權有效地結合起來,高地址部分權值高,低地址部分權值低。
其它值被保留,在未來必要時將被賦予新的編碼。
e_ident[EI_VERSION]
給出了ELF頭的版本號。目前這個值必須是EV_CURRENT,詳情請看等下的e_version
。
e_ident[EI_PAD]
給出了e_ident
中未使用位元組的開始地址。這些位元組被保留並置為0。
處理目標文件的程序應該忽略它們。如果之後這些位元組被使用,EI_PAD
的值就會改變。
e_type
用來定義文件的類型。
名稱 | 值 | 意義 |
---|---|---|
ET_NONE | 0 | 無文件類型 |
ET_REL | 1 | 可重定位文件 |
ET_EXEC | 2 | 可執行文件 |
ET_DYN | 3 | 共享目標文件 |
ET_CORE | 4 | 核心轉儲文件 |
ET_LOOS | 0xfe00 | 操作系統指定 |
ET_HIOS | 0xfeff | 操作系統指定 |
ET_LOPROC | 0xff00 | 處理器指定 |
ET_HIPROC | 0xffff | 處理器指定 |
雖然核心轉儲文件的內容沒有被詳細說明,但ET_CORE
還是被保留用於標誌此類文件。從ET_LOOS
到ET_HIOS
(包括邊界)會被保留用於操作系統處理的場景。而從ET_LOPROC
到ET_HIPROC
(包括邊界)則會被保留用於處理器指定的場景。其它值在未來必要時可被賦予新的目標文件類型。
e_machine
用來定義當前文件的機械架構。
名稱|值|意義|
|:——|:——|:——|
|EM_NONE|0|無機械類型|
|EM_M32|1|AT&T WE 32100|
|EM_SPARC|2|SPARC|
|EM_386|3|Intel 80386|
|EM_68K|4|Motorola 68000|
|EM_88K|5|Motorola 88000|
|EM_860|7|Intel 80860|
|EM_MIPS|8|MIPS I Architecture|
當然還有其他類別的機械結構。
e_version
用來顯示文件當前版本。
名稱|值|意義|
|:——|:——|:——|
|EV_NONE|0|無效版本|
|EV_CURRENT|1|目前版本|
e_entry
這一項給系統轉交控制權給ELF中的代碼的虛擬地址。如果沒有相關入口項(Associated entry point),則這一項為0。
e_phoff
這一項給出程序頭部表在文件中的位元組偏移(Program Header table Offset)。如果文件中沒有程序頭部表,則為0。
e_shoff
這一項給出節頭表在文件中的位元組偏移(Section Header table Offset)。如果文件中沒有節頭表,則為0。
e_flags
這一項給出文件中與特定處理器相關的標誌,這些標誌命名格式為EF_machine_flag
。
e_ehsize
這一項給出ELF文件頭部的位元組長度(ELF Header Size)。
e_phentsize
這一項給出程序頭部表中每個表項的位元組長度(Program Header Entry Size)。每個表項的大小相同。
e_phnum
這一項給出程序頭部表的項數(Program Header entry Number)。因此,e_phnum
與e_phentsize
的乘積即為程序頭部表的位元組長度。如果文件中沒有程序頭部表,則該項值為0。
e_shentsize
這一項給出節頭的位元組長度(Section Header Entry Size)。一個節頭是節頭表中的一項;節頭表中所有項占據的空間大小相同。
e_shnum
這一項給出節頭表中的項數(Section Header Number)。因此,e_shnum
與e_shentsize
的乘積即為節頭表的位元組長度。如果文件中沒有節頭表,則該項值為0。
e_shstrndx
這一項給出節頭表中與節名字串表相關的表項的索引值(Section Header Table Index related with Section Name String Table)。如果文件中沒有節名字串表,則該項值為SHN_UNDEF。關於細節的介紹,請參考後面的「節」和「字串表」部分。
程序的頭部只有對於可執行文件和共享目標文件有意義。其中,ELF文件的頭中的e_phentsize
和e_phnum
項指定了相應的程序頭的大小。程序頭的數據結構如下
1 | /* Program segment header. */ |
字段 | 說明 |
---|---|
p_type | 表明了對應數組元素的類型或表面了如何解釋該數組元素,具體信息可看待會描述的p_type的段類型 |
p_offset | 此字段為文件開始到段開頭第一字節的偏移 |
p_vaddr | 第一字節內存的虛擬地址 |
p_paddr | 用於物理地址尋址相關系統裡面,由於System V忽略了應用程序的物理尋址,因此可執行文件和共享文件的該項內容並沒有被限定 |
p_filesz | 表明文件鏡像中該字段的大小,可以為0 |
p_memsz | 表明內存鏡像中該字段的大小,可以為0 |
p_flags | 給出和段相關的標記,具體信息可看待會的描述 |
p_align | 需加載程序段的p_vaddr 以及p_offset 的大小為page的整數倍。該成員給出了段文件和內存中對齊方式。若該數值是0或者1,表示不需要對齊。此外,p_align 是2的整數指數次方,並且p_vaddr 與p_offset 在Modulo p_align的意義下應該相等。詳情請看待會描述 |
p_type的段類型
數值|名字|意義|
|:——|:——|:——|
|0x00000000|PT_NULL|表明段還沒被使用|
|0x00000001|PT_LOAD|是可加載的段,大小由p_filesz
和p_memsz
來決定。文件中的位元組被映射到相應記憶體段開始處。如果p_memsz
大於p_filesz
,剩餘」的位元組都會變成0。p_filesz
不能大於p_memsz
。可載入的段在程序頭部中按照p_vaddr
的升序排列。|
|0x00000002|PT_DYNAMIC|和動態鏈接信息有關|
|0x00000003|PT_INTERP|給出以NULL為结尾的字符串的位置和長度。該字串將被當作解釋器調用。這種段類型僅對可執行文件有意義(也可能出現在共享目標文件中)。此外,這種段在一個文件中最多出現一次。而且這種類型的段存在的話,它必須在所有可載入段項的前面。
|0x00000004|PT_NOTE|給出附加信息的位置和大小。|
|0x00000005|PT_SHLIB|該段類型被保留,不過語義未指定。而且,包含這種類型的段的程序不符合ABI標準。|
|0x00000006|PT_PHDR|該段類型的數組元素如果存在的話,則給出了程序頭部表自身的大小和位置,既包括在文件中也包括在記憶體中的訊息。此類型的段在文件中最多出現一次。此外,只有程序頭部表是程序的記憶體映像的一部分時,它才會出現。如果此類型段存在,則必須在所有可載入段項目的前面。|
|0x70000000|PT_LOPROC|略|
|0x7FFFFFFF|PT_HIPROC|略|
基地址-Base Address
用途:在動態連結期間重新定位程序。
1.程序頭部的虛擬地址可能並不是程序記憶體鏡像中實際的虛擬地址。可執行程序通常都會包含絕對地址的代碼。
2.為了使得程序可以正常執行,段必須在相應的虛擬地址處。
3.共享目標文件通常來說包含與地址無關的代碼。這可以使得共享目標文件可以被多個進程載入,同時保持程序執行的正確性。
4.系統會為不同的進程選擇不同的虛擬地址,也會保留段的相對地址,因為地址無關代碼使用段之間的相對地址來進行定址,記憶體中的虛擬地址之間的差必須與文件中的虛擬地址之間的差相匹配。
5.記憶體中任何段的虛擬地址與文件中對應的虛擬地址之間的差值對於任何一個可執行文件或共享對象來說是一個單一常量值。這個差值就是基地址。
可執行文件或者共享目標文件的基地址是在執行過程中由以下三個數值計算的。
要計算基地址,首先要確定可載入段中p_vaddr
最小的記憶體虛擬地址,之後把該記憶體虛擬地址縮小為與之最近的最大頁面的整數倍即是基地址。根據要載入到記憶體中的文件的類型,記憶體地址可能與p_vaddr
相同也可能不同。
ELF可重定位文件裡面有不同大小的條目(entry)。這些條目組成了節頭部表(Section Header Table)。如下圖所示:
在linux裡面查看Elf Section Header的方式是輸入readelf -S SimpleSection.o
。
在這裡我們可以看到一共有13個條目(節)。以下我會說明這些節的作用。
.text
存放已編譯程序的代碼。
.rodata
用來只讀數據
.data
存放已初始化的全局和靜態C變量。而局部的C變量則會在運行時保存在棧中。
.bss
和上面相反,只存放未初始化的全局C變量。在目標文件中,该節只是佔位符,不占用實際空間。
.symtab
符號表,存放程序中被定義和引用的函數和全局變量的信息。另外,它不包含局部變量的表目。
.rel.text
和其他文件連結時,.text
節中任何調用外部函數或引用全局變數的指令都需要修改(調用本地函數的指令不需要修改)。
.rel.data
被模組定義或引用的任何全局變數的訊息,.data
節中任何已初始化全局變數的初始值是全局變數或外部定義函數的地址都需要修改。
可執行目標文件不需要重定位訊息,通常省略.rel.text
和.rel.data
。
.debug
調校符號表,以-g
選項編譯時得到。包含如定義的局部變數和類型定義,定義和引用的全局變數,原始的C源文件。
.line
原始的C源文件中的行號和.text節中機器指令之間的映射,以-g
選項編譯時得到。
.strtab
字串表,是以null結尾的字串序列,包含.symtab和.debug節中的符號表,節頭部中的節名字。
.line
原始的C源文件中的行號和.text節中機器指令之間的映射,以-g
選項編譯時得到。
.strtab
字符串表,是以null結尾的字符串序列,包含.symtab
和.debug
節中的符號表,節頭部中的節名字。
有3種符號:
符號表是匯編器構造的,它是一個包含了以下條目的數組。1
2
3
4
5
6
7
8
9typedef struct {
int name; /* String table offset */
char type:4, /* Function or data */
binding:4; /* Local or global */
char reserverd; /* Unused */
short section; /* Section hearder index */
long value; /* Section offset or absolute address */
long size; /* Object Size in bytes*/
} Elf64_Symbol;
/ Symbol table entry. /
typedef struct
{
Elf32_Word st_name; / Symbol name (string tbl index) /
Elf32_Addr st_value; / Symbol value /
Elf32_Word st_size; / Symbol size /
unsigned char st_info; / Symbol type and binding /
unsigned char st_other; / Symbol visibility /
Elf32_Section st_shndx; / Section index /
} Elf32_Sym;
typedef struct
{
Elf64_Word st_name; / Symbol name (string tbl index) /
unsigned char st_info; / Symbol type and binding /
unsigned char st_other; / Symbol visibility /
Elf64_Section st_shndx; / Section index /
Elf64_Addr st_value; / Symbol value /
Elf64_Xword st_size; / Symbol size /
} Elf64_Sym;
在Linux裡面若要將幾個指令連在一行直接運行,可以使用|
。例子:查看當前目錄下文件列表裡文件名為car的文件。
Command:ls | grep car
http://blog.hac425.top/categories/ctf/
https://github.com/hacksysteam/HackSysExtremeVulnerableDriver
https://hshrzd.wordpress.com/2017/05/28/starting-with-windows-kernel-exploitation-part-1-setting-up-the-lab/
https://bbs.pediy.com/thread-218838.htm
Write Once, Pwn Anywhere in BlackHat 2014
https://github.com/bruce30262/x86_shellcode_tutorial
Scraps of notes on remote stack overflow exploitation
The House Of Lore: Reloaded ptmalloc v2 & v3: Analysis & Corruption
Kernel instrumentation using kprobes
Infecting loadable kernel modules: kernel versions 2.6.x/3.0.x
A Eulogy for Format Strings
Dynamic Program Analysis and Software Exploitation
Phrackerz: Two Tales
Exploiting DLmalloc frees in 2009
Exploiting TCP Persist Timer Infiniteness
Linux Kernel Heap Tampering Detection
How close are they of hacking your brain
A brief history of the Underground scene
Attacking the Core: Kernel Exploitation Notes
Automated vulnerability auditing in machine code
Hacking deeper in the system
https://github.com/pandazheng/LinuxExploit
http://phrack.org/issues/57/8.html#article
http://phrack.org/issues/57/9.html#article
http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html
https://github.com/0xAX/linux-insides/blob/master/SysCall/syscall-4.md
http://eleveneat.com/2015/07/26/Software-Security-Week1/
http://eleveneat.com/2015/08/14/Software-Security-Week2/
https://403forbidden.website/2017/09/%e4%ba%8c%e8%bf%9b%e5%88%b6%e6%bc%8f%e6%b4%9e%e5%ad%a6%e4%b9%a0%e8%bf%9e%e8%bd%bd-0/
http://staff.csie.ncu.edu.tw/hsufh/COURSES/SPRING2018/attackdefense.html
http://cybersecurity.upv.es/attacks/offset2lib/offset2lib.html#intro
http://blog.nsfocus.net/null-pointer-vulnerability-analysis-defense/
http://codearcana.com/posts/2013/05/21/a-brief-introduction-to-x86-calling-conventions.html
Sour Pickles – Python pickle problems
Sonic Hacking Utilities
GDB Example ncurses
Exploring Python using GDB
Exploiting PHP File Inclusion
Address Sanitizer
OWASP Top 10 - Presentatioin on Top 10 Web Application Vulnerabilities and how to avoid them.
Vudo malloc tricks
Once upon a free()
RSA Attacks - Explanation of various RSA attacks
How the heck do we get to main()?
Malloc Internals - glibc wiki
10 things InfoSec professionals need to know about networking
ELF executable reconstruction from a core image
要將C文件轉化成電腦可執行的文件,需要用編譯器將該文件轉化成電腦可讀懂的格式-二進制。我會使用編譯器GCC做例子來讓大家更明白其執行的過程。
首先我們要有一個C文件。
1 | //hello.c |
在Unix裡面執行gcc -o hello hello.c
,此時編譯器便會讀取hello.c且將它轉成二進制文件。轉換過程如下。
這過程總共有4個階段:
預處理器(cpp)會根據C文件裡面的#的命令來讀取Header,例如在這裡會讀取stdio.h, 然後將其內容加入原本的C文件裡面,生成一個以.i作為擴展名的文件。
再來,如果只想進行預處理可輸入gcc -E hello.c -o hello.i
。預處理階段,主要是處理源代碼裡面含有#
字符的指令。
例如: “#include”,”#define”。
然後編譯器會把hello.i轉成hello.s,也就是所謂的匯編語言程序。gcc -S hello.i -o hello.s
變成彙編語言程序後的源代碼如下:
1 | main: |
然後就匯編器就可以派上用場啦,它能將hello.s轉成機械語言指令,再把指令變成可重定位目標程序(Relocatable object program)的格式,存放在hello.o中。as hello.s -o hello.o
因為這裡helloc程序用了printf函數。此函數其實是本來就屬於標準C Library裡面的一個函數要調用此函數,我們就必須用到鏈接器(ld)將函數合拼到hello.o裡面,完成這過程後,最終也生成了可以被系統執行的hello文件(可執行目標文件)。
由於,鏈接器需要用到一大堆文件把hello.o鏈接起來,才可以把源文件變成最終的可執行目標文件。所以我會在介紹鏈接文件的文章裡面讓大家了解當中的原因。
在命令行輸入./hello
,系統便會運行hello程序,也會返回結果hello,world在你的Shell裡面。
在整個編譯流程裡面,你的源代碼會經過以下六個步驟變成最終目標代碼。
例子:未優化的代碼1
2
3
4
5movl index, %ecx
addl $4,%ecx
mull $8,%ecx
movl index,%eax
movl %ecx,array(,eax,4)
優化後:1
2
3movl index, %edx
leal 32(,%edx,8),%eax
movl %eax,array(,%edx,4)
這裡只需要了解代碼被優化了,其代碼代表什麼在這文章並沒有討論意義。
包括了總線,I/O設備,主存還有處理器。
虛擬內存是一種當CPU內存不夠的時候而需要用到的一種技術,它允許CPU的每一個進程都擁有一個私有的虛擬地址,這樣能使到每一個進程都可以看到一樣的內存空間。下圖是Linux進程使用虛擬地址的例子。至於裡面各區域的詳細解釋以後會在別的文章為你們一一介紹。
This is the writeup on how I solve the 2016 SANS Holiday Hack Challege
故事發生在一個夜深人靜的晚上,喬斯(Josh Doise)和傑西卡(Jessica Doise)在睡覺的時候聽到聖誕老人竟然出現在他們家裡的聲音。但正當他們決定要去看看聖誕老人的真面目時,發生了一些十分奇怪的事情,一陣禮物被撕破的聲音從他們家樓下傳出來。他們還聽到尖銳的打鬥聲,很可惜的是,在他們去到樓下時候,聖誕老人已經不見了,只見到家裡一片混亂,家裡的聖誕樹還甚至被劈開一半呢。為了調查事件的發生你們將開始一段新的冒險。在我進入遊戲教程前,我想先說這個遊戲裡面所有的挑戰都是他們設計的:
在這裡感謝他們設計的挑戰讓我學到新的Forensic知識。想進入遊戲挑戰自己的人可以按這裡
遊戲一開始你就會身處在聖誕老人不見了的案發現場。在和喬斯和傑西卡對話後,你知道你需要調查那張留在現場神秘的卡片。這張卡片留下了聖誕老人的Twitter戶口以及Instagram戶口。
仔細調查後,你可以發現到聖誕老人的Tweet隱藏着其他信息。如果想快速獲取聖誕老人留下的所以信息你可以用tweet_dumper.py,一次過將所有對話save成CSV文件。當你成功把所有對話都整齊排列好你會看到所有的信息會組成一個很大而且明顯的信息,那就是:BUGBOUNTY。
你也可以在http://twlets.com/ 這個網站直接將自己或他人Twitter的信息變成CSV文件。
接著你可以查看聖誕老人的Instagram,在第一張照片找到了2個Zip File的提示。
提示1:電腦上出現了Zip file的名字:SantaGram_v4.2.zip
提示2:紙張上有這個網站http://www.northpolewonderland.com/
憑著這兩個提示你可以聯想到的是Zip File的位置可能就是:http://www.northpolewonderland.com/SantaGram_v4.2.zip 。經過嘗試後你就會成功下載到那個Zip File。裡面有一個SantaGram_4.2.apk的文件。
接下來的故事發展,你會通過一個禮物袋來到一個冰天雪地的地方。沒錯,這裡就是聖誕老人和他的精靈居住的地方,北極。這時候你會見到Holly Evergreen。他會告訴你以下幾件事情:
零件的所在地:[以後補充]
為了找回失踪的聖誕老人,你必須想辦法去知道Santagram_4.2.apk 這個文件裡面到底隱藏了什麼信息。在北極尋找了一段時間後,你可以在聖誕老人工作室的火車站找到Shinny Upatree。他會告訴你怎樣去分析你找到的APK文件。從他口中你明白到了以下的事情:
得到這些有用的情報後,你可以開始分析你得到的Apk文件了。正當你Unzip的時候發覺你需要輸入密碼才能繼續你的分析,不然你就無法繼續下去。其實,我在解題的時候在這裡卡了很久的一段時間,直到我在Reddit那邊見到有一個人給予的提示:你可能已經一早獲得了Unzip Santagram的密碼,只是你自己沒察覺到而已。我腦中醒起會不會是之前的BUGBOUNTY。最後,皇天不負有心人,我成功找到密碼(bugbounty)啦。進入分析Apk的階段,你可以用JadX 去Decompile 你得到的Apk文件,一旦Jadx成功Decompile後,你就能找題目要求你的username and password。使用Text Search功能你可以找到username and password 都隱藏在Code裡面。這段Code你可以在northpolewonderlad.santagram.SplashScreen Class裡面找到。
1 | jSONObject.put("username", "guest"); |
另外,題目要求的Audio Component你可以在res/raw裡面找到,文件名稱為:discombobulatedaudio1.mp3。Unzip Santagram的Apk你也可以的直接得到該Mp3 File。
unzip Santagram_4.2.apk
如果想要該Mp3文件,可以到這裡下載
在解決了apk的文件後,你終於可以靜下心來研究一下你剛剛得到的Cranbian image。要知道怎樣使用這個Image你可以找在聖誕樹下的Wunhorse Openslae來詢問。從他口中你明白到了以下的事情:
當你Unzip disk image後,你可以按照以下步驟來打開Cranbian image。
fdisk -l cranbian-jessie.img
command你可以得知這個Image由2個部分組成。而你要找的資料是在第二個部分裡面。你也會知道開始的Sectors會是137216。 mount -v -o offset=70254592 -t ext4 cranbian-jessie.img mnt/
你就能成功Mount Cranbian Image。這個Mount Command裡面的 -v 是verbose, 會顯示更多正在Run着的Command的資訊。-o options列出還要使用的Option。 -t = type System file的種類, 而最後的/mnt是我自己設定的Mount Point.你可以用mkdir來建立一個你要的Mount point。根據題目要求,你需要找出Cranpi account的Password。一般來說,Linux存儲密碼的位置會放在/etc/shadow
File裡面。而這些密碼都會用某些演算法進行加密再被存儲到這個位置。用cat mnt/etc/shadow
,會得到Cranpi account密碼被hashing後的value。
要找會原來的值(密碼),你需要將Hash值還原回原本的文字。在Kali Linux裡面John the ripper是一個非常優秀的密碼破解工具。為了減輕破解密碼的難度,住在Small Tree house的Minty Candycane給了你最有用的提示,用Rockyou.txt來配合Crack的過程。使用方法是,在Linux Shell裡面打john --wordlist=rockyou.lst mnt/etc/shadow
就會開始進行Password Cracking。破解後的密碼是yummycookies。
然後把你得到的密碼告訴Holly Evergreen,他就會Unlock Cranbian Pi的Account讓你使用。
現在你可以用Cranbian Pi去啟動遊戲裡面每個Terminal了。
當你找到Terminal後,會見到旁邊有一個被密碼上鎖的門。你需要好好利用Terminal裡面的資訊來找到門的密碼。
一旦你Access Terminal後,你會見到這句話
To open the door, find both parts of the passphrase inside the /out.pcap file
待補充
]]>Markdown是一種輕量級的標記語言,其用簡單的標記語法便可達到排版的目的,其可以使我們更加專注於內容的編寫,而不需過多關注排版。本文主要整理了 Markdown中的常用的標記語法,以便自己與他人以後查用。
<div class="note">default</div>
<div class="note default">default</div>
這是咖啡好喝嗎?
這是雪糕甜甜的
這是布丁請你吃哦!
在了解編碼是怎麼一回事之前,我們必須要先知道2個概念,那就是位和字節。位(bit)是指電腦裡面存放的二進制數值=0或者1。而只要有8個位便可稱之為字節(byte)。例子:01000001,在16進制裡面,這個字節=0x41。
字符編碼的意思是電腦會使用某種規則將平時我們日常生活中會用到的一些文字/符號轉換成電腦可以讀取的二進制數字進行相互的轉換。
例子:電腦使用ASCII字符集來進行字母“A”的轉換。01000001(0x41)<-> 65 <-> 'A'
在編碼時,這些規則就會用所謂的字符集來處理字符和二進制數字代碼之間的轉換。
而字符集則是一個系統支持的所有抽象字符的集合。這些字符就是各種文字和符號的總稱。通常包括了各個國家文字、標點符號、圖形符號、數字等等。
未完待續
]]>Debug是DOS和Windows裡面專門調試程序以及讓你在電腦上編寫匯編語言一種工具。一般上,我們可以使用它,來查看CPU各種寄存器中的內容、內存的情況和在機器碼級跟蹤程序的運行。而Debug指令只能在這些版本的Windows內使用:Windows® 9x/Me,Windows® NT/2000/XP/2003。而在之後版本的Windows就再也無法使用這個指令了。Debug最初的設計是用來處理.最大容量可達到65280 (6xx1024-256)bytes或少於此大小的.COM文件。而至於少過多少,那就得取決於程序必須在堆棧上同時放置的最大字節數。為什麼一定要減掉256字節呢?那是因為DEBUG經常使用從00到FF十六進制偏移量的區域來存儲一些內部數據,例如加載的文件的名字。所以.COM程序應該只能是用在單個內存段裡面(只有64 KiB)。
這裡先簡單介紹會用到的Debug指令的Option。
-r
查看、改變CPU寄存器的內容-d
查看內存中的內容-e
改寫內存中的內容-u
將內存中的機器指令翻譯成匯編指令-t
執行一條機器指令-a
以匯編指令的格式在內存中寫入一條機器指令。P/s:本教程會以Windows2000作為例子。
要使用Debug這個指令,你需要在CMD中輸入debug,之後你就可以開始使用各種Debug相關的指令。先用-r
來查看各個寄存器的當前情況吧。
然後我們試試看用-r 寄存器
來修改他們的值吧。輸入-r ax
,在出現:
後輸入1111,你的AX就會等於1111。
現在的CS:IP為0AD8:0100。而你也可以看到機器碼顯示的位址為D3990075。輸入-r ip
,再把IP修改成200。
最後輸入-r cs
把CS修改成ff00。
現在我們要用-d
指令來看內存中的內容。以下例子為0AD8H處的內容。輸入後,你可見到這個指令列出了0AD8:0200到0AD8:027F的完整內容。
格式為-d 段地址:偏移地址
從圖來看左邊顯示的是每行的起始地址。最右邊對應的就是顯示的ASCII碼字符。現在我們再看另一個例子,這次我們會使用-e
改寫內存中的內容。輸入後看到的結果如下:
現在,我們來學一下怎樣用-e
指令來寫入機械碼。假設我們要輸入以下的機械碼。然後再使用-u
查看你刚刚輸入的機械碼和對應的匯編指令。
機械碼 | 所對應的匯編指令 |
---|---|
b8 01 00 | mov ax,0001 |
b9 02 00 | mov cx,0002 |
01 c8 | add ax,cx |
在使用-t
去執行我們剛剛寫入的指令前我們必須先確認CS:IP已經指向了1000:0。你們可以看到下圖所示,我用了-r
把CS:IP指到我要的位址去。
現在可以輸入-t
指令,你可以看到指令mov ax,0001
被執行了,而此時ax也變成了1,IP變成了0003,因為這個指令共用了3個字節。
繼續用-t
指令看看接下去的變化吧。
由於使用-e
一個一個輸入機器代碼實在太麻煩了,所以你可以用-a
這個Option来讓你直接輸入匯編指令,而不是機械代碼。比如說下面我就從CS:IP=1000:0那邊開始輸入我的匯編指令。要結束你的輸入只需要在給出的起始地址後按Enter鍵就行了。
Task A
请用-e
和-a
输入下表提供的機械碼和匯編語言
機械碼 | 所對應的匯編指令 |
---|---|
b8 20 4e | mov ax,4E20H |
05 16 14 | add ax,1416H |
bb 00 20 | mov bx,2000H |
01 d8 | add ax,bx |
89 c3 | mov bx,ax |
01 d8 | add ax,bx |
b8 1a 00 | mov ax,001AH |
bb 26 00 | mov bx,0026H |
00 d8 | add al,bl |
00 dc | add ah,bl |
00 c7 | add bh,al |
b4 00 | mov ah,0 |
00 d8 | add al,bl |
04 9c | add al,9CH |
-e
指令的執行
再用-t
,觀看其執行的狀況。
-a
指令的執行
再用-t
,觀看其執行的狀況。
HackMD 是一個跨平台的Markdown即時協作筆記。所以你可以和朋友們在電腦、平板甚至是手機上同一時間製作你們的筆記。最方便的就是,你可以在首頁透過Facebook、Twitter、GitHub、Dropbox以及Google來登入HackMD。
你可以輕易的複製文件的網址來分享此文件。
在頁面的右上方有個小按鈕,你可以透過以下選項來更改權限:
隨意:任何人都可以編輯以及瀏覽這份筆記。
可編輯:已經登入的使用者才可以編輯這個筆記。(客人可以瀏覽)
限制:已經登入的使用者可以編輯這個筆記。(禁止客人瀏覽)
鎖定:只有擁有者可以更改這份筆記。(客人可瀏覽)
保護:只有擁有者可以更改這份筆記。(禁止客人瀏覽)
私有:只有擁有者可以更改與檢視這份筆記。
只有筆記的擁有者可以更改權限。
電腦 & 平板
檢視:只看到結果。
同時:同時看到兩邊。
編輯:只看到編輯器。
手機
檢視:只看到結果。
編輯:只看到編輯器。
你可以在點擊Menu功能後,從 Dropbox 、Google Drive 、Gitgist 匯入 .md 或是從剪貼簿Clipboard 匯入。至於匯出也一樣如此。
你可以將此Markdown文件在下載的時候轉換成以下格式:
上傳圖片
只要按下這個按鈕
或是 拖放 圖片到編輯器,甚至 貼上 圖片也可以喔!
這會自動上傳圖片至 imgur,啥都不必煩惱了 🤖
你可以在HackMD自由的使用表情符號
😭 😓 😪 😴 🙄 🤔 😍 😘 😗 😁 😆 😅 😂
完整的表情符號列表在這裡
除此之外,HackMD還具備了讓你將MarkDown文件變成簡報模式和書本模式的功能。那樣你就可以直接用此來進行你的Presentation或者輕鬆的向看電子書那樣,閱讀你的MarkDown文件。
在同時模式裡面,你可以再右下角找到目錄的小按鈕 。當你按下之後,他會顯示出你當前所在的區塊,以及完整的目錄表。若想跳轉到其他區塊,你只需要點擊目錄裡面列出的章節題目就可。
可以在這網站找到一些快捷鍵來提升你的文件處理的效率。
提供完整的 Markdown 自動完成與提示。
:
#
[]
{}
!
1 | var s = "JavaScript syntax highlighting"; |
如果想要行號,在表明程式語言之後輸入
=
以及想處於的行號碼=101
。
您也可以指定開始行號,如下所示,行號從101開始。
這就是顯示後的樣子。
或是可以接續上一個程式碼區塊的行號,使用
=+
。
本人用Python Code的例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import sys
from sympy.solvers import solve
from sympy import Symbol
# This comes from https://github.com/sourcekris/RsaCtfTool/blob/master/wiener_attack.py
# He made it, and I am incorporating it into my Factorizer.
# A reimplementation of pablocelayes rsa-wiener-attack for this purpose
# https://github.com/pablocelayes/rsa-wiener-attack/
class WienerAttack(object):
def rational_to_contfrac (self, x, y):
a = x//y
if a * y == x:
return [a]
else:
pquotients = self.rational_to_contfrac(y, x - a * y)
pquotients.insert(0, a)
return pquotients
如同以下方式來使用標籤,它們會顯示在您的歷史紀錄。
要寫tags: + 筆記
教程
作業
顯示結果如下
提供描述筆記的資訊,以進階設定瀏覽行為,詳細請至上連結。
你可以使用以下語法,表明自己的 姓名、時間與顏色 並與其他的引用區塊做區別。
[name=Milo] [time=Sun, October 22, 2017 9:59 PM] [color=#907bf7]也支援巢狀引用區塊喔!
[name=Milo] [time=Sun, October 22, 2017 10:00 PM] [color=red]
顯示結果如下
Youtube
用這格式輸入可公開Youtube視頻鏈接的代號
例子:輸入{}
,然後在裡面加上%youtube CJ9xqHAdFjM %
Vimeo
用這格式輸入可公開Vimeo視頻鏈接的代號
例子:輸入{}
,然後在裡面加上%vimeo 230308008 %
用這格式輸入可公開Gist
例子:輸入{}
,然後在裡面加上例子:輸入{}
,然後在裡面加上%gist schacon/4277 %
輸入{}
,括號裡面再輸入%slideshare HacksInTaiwan/ctf-56046764 %
你的Hackmd.io就會有以下的顯示
輸入{}
,括號裡面再輸入%speakerdeck sugarenia/xxlcss-how-to-scale-css-and-keep-your-sanity %
你的Hackmd.io就會有以下的顯示
注意:請使用 https 的網址,否則可能會被您的瀏覽器阻擋載入。
輸入{}
,括號裡面再輸入%pdf https://beginners.re/RE4B-EN.pdf %
你可以使用 MathJax 語法來產生LaTeX 數學表達式,如同 math.stackexchange.com:
The Gamma function satisfying $\Gamma(n) = (n-1)!\quad\forall n\in\mathbb N$ is via the Euler integral
$$
x = {-b \pm \sqrt{b^2-4ac} \over 2a}.
$$
$$
\Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.
$$
更多關於 LaTeX 數學表達式 請至這裡
您可以像是以下使用循序圖:
在程式碼區域輸入sequence
你的Hackmd.io就會有以下的顯示
更多關於 循序圖 語法 在這裡.
您可以像是以下使用流程圖:
在程式碼區域輸入flow
你的Hackmd.io就會有以下的顯示
更多關於 流程圖 語法 在這裡.
在程式碼區域輸入graphiz
你的Hackmd.io就會有以下的顯示
更多關於 Graphviz 語法 在這裡
在程式碼區域輸入mermaid
你的Hackmd.io就會有以下的顯示
更多關於 Mermaid 語法 在這裡
輸入:::success成功板塊:::
:::info公佈信息:::
:::warning注意一下:::
:::danger危險地帶:::
你的Hackmd.io就會有以下的顯示
1 | # h1 標頭 |
1 | ___ |
輸入1
(c) (C) (r) (R) (tm) (TM) (p) (P) +-
會顯示這樣
“Smartypants, 雙引號”
‘Smartypants, 單引號’
輸入1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17**這是粗體文字**
__這是粗體文字__
*這是斜體文字*
_這是斜體文字_
~~這是刪除文字~~
上標: 19^th^
下標: H~2~O
++這是底線文字++
==這是標記文字==
會顯示這樣
1 | > 引用區塊也可以是巢狀的喔... |
引用區塊也可以是巢狀的喔…
…可以多層次的使用…
…或是用空白隔開
1 | + 在行開頭使用 `+` `-` 或是 `*` 來建立清單 |
+
-
或是 *
來建立清單Integer molestie lorem at massa
您可以逐次增加項目數字…
1.
從其他範圍開始編號清單
1 | | 選項 | 描述 | |
選項 | 描述 |
---|---|
data | path to data files to supply the data that will be passed into templates. |
engine | engine to be used for processing templates. Handlebars is the default. |
ext | extension to be used for dest files. |
1 | | 選項 | 描述 | |
選項 | 描述 |
---|---|
data | path to data files to supply the data that will be passed into templates. |
engine | engine to be used for processing templates. Handlebars is the default. |
ext | extension to be used for dest files. |
1 | | 選項 | 描述 | |
選項 | 描述 |
---|---|
data | path to data files to supply the data that will be passed into templates. |
engine | engine to be used for processing templates. Handlebars is the default. |
ext | extension to be used for dest files. |
1 | | 選項 | 描述 | |
選項 | 描述 |
---|---|
data | path to data files to supply the data that will be passed into templates. |
engine | engine to be used for processing templates. Handlebars is the default. |
ext | extension to be used for dest files. |
顯示出來的結果(只放部分圖片)
顯示出來的結果
你的Markdown文字最後也會出現你之前寫下的Footer。
使用後的結果如下
這是 HTML 的縮寫範例
它會轉換 “HTML”,但是縮寫旁邊其他的部分,例如:”xxxHTMLyyy”,不受影響
最後顯示成這個樣子
Discord是一個完全免費,且具備超多強大功能的語音通訊平台。而且,還有漂亮又簡單的界面,讓你輕鬆的建立你的文字和語音頻道。不僅如此,Discord不像QQ那樣會自帶廣告,所以你可以少掉被廣告洗腦的煩惱。
另外,你也可以應用各式各樣的機械人Bot來加強你頻道內的功能。例如:像電台那樣自動播放歌曲,用指令來投骰子,像玩RPG game升級系統那樣通過聊天中獲取經驗值,進行投票活動和個人備忘錄等等。此外,你還可以在不同頻道/子頻道擁有多過一個的暱稱。再來,只要你喜歡你還可以自己設定可愛的自定義身份呢。
最重要的一點,Discord的支援十分全面,你可以在Windows,Mac OS,Linux,Android以及Ios上使用Discord來。當你在直播遊戲時,你也可以用Discord和他人進行談話,這是因為你可以用不同平台的賬號如:Youtube、Twitch、Steam、Skype等等來連接你的Discord Server。。
更完整的功能和教學,請記得留守我下一篇的文章。
下一篇預告:如何成為Discord達人
]]>雙引號” “來做精準搜尋
搜索结果裡面的網站內容必須出現完全一樣的搜索關鍵詞,因此當你想尋找精準的內容時,你可以在在搜索關鍵詞上加上雙引號。
例子: "量子能量塔"
用
-
來排除不必要的搜尋結果
當你想搜索關鍵詞並且排除包含某個字詞的結果你可以在該字詞前面加上-
來移除這系列的搜索結果。
例子:kotlin -kotlinlang.org
這表示你尋找和kotlin有關的資料時,移除了所有kotlinlang.org的搜索結果。
用
+
來確保某個字詞出現在搜尋結果內
要在搜索結果的網站內包含一些指定的文字的話,+
這個符號可以做到這個功能。
例子:+
待更新
待更新
待更新
待更新
http://www.anybeen.cn/share.php?id=83c32ZRZdVLwSiGE9jrr
https://www.zhihu.com/question/28013848
http://www.sowang.com/seek.htm
http://blog.joaoko.net/archives/222
https://www.0101tx.com/about/
一般上,我們都會用Python編譯器來運行py文件。而當我們查看py文件的時候,我們都可以直接看到程式的源代碼。然而,因為商業的需求,開發者必須想辦法保護程式源代碼,於是便有了pyc和pyo這2種的文件。
pyc是而二进制文件的一種。要生成此文件,我們必須先將py文件經過編譯後,再使用python -m compileall <your_script.py>
來生成你要的pyc文件。pyc文件和py文件比較起來,加載的速度會快了一些。另外,要注意的是不同版本的Python編譯出來的pyc文件也會有所不一樣。
pyo是經過優化編譯後的程序。python -O <your_script.py>
便可以直接生成所謂的pyo文件。小提示,python3.5版本以上都一律採用了新的優化機制,所以只有pyc,而沒有使用pyo文件了。
pyd是python的动态链接库。
或許有人會問,那要怎樣從pyo找回源代碼呢?用uncompyle6 2.13.2工具可以將pyc文件的binary code反編譯回原來的代碼。
例子:
安装好uncompyle6后,可在cmd输入uncompyle6 <your_script.pyc>
,你就能得到原本的源代码。
此外,這裡有個線上工具也具有一樣的功能哦。你可以上載pyc文件,然後它會自動幫你轉回源代碼。
隱寫術是將想要隱藏的消息嵌入到載體中,而達到信息保密的效果。隱寫術的使用可以追溯到古埃及時代又或者中國的元朝。而現代隱寫術通過使用電腦以及不同的隱寫軟件將信息隱藏在不同種類的文件當中。
另外,使用隱寫術也可以為加密的信息提供多一層的保護。也就是說,我們可以將加密後的信息用一些非常普通的文件,如圖片,音頻,視頻,文檔等等,經過一系列的特殊處理將其隱藏起來。
一個完整的隱寫系統包含了4個要素:
最低有效位(Least Significant Bit)代表着二進制數中的最小的單位,可以用來指示數字很小的變化。也就是說,LSB是一個二進制數字中的第0位(即最低位),具有權值為$2^0$,可以用它來檢測數的奇偶性。在大端序(Big Endian)中,LSB指最右邊的位。
舉個例子,在圖像隱寫術裡面,所謂的LSB隱寫就是去修改RGB的顏色分量中的最低位。也就是去修改像數最低的1位元。當然人類的眼睛是無法分辨得出當中的變化,唯有通過一些軟件去檢驗,才能得知圖片裡面是隱藏了信息。
元數據,又稱中介數據、中繼數據,為描述數據的數據(data about data),主要是描述數據屬性(property)的信息,用來支持如指示存儲位置、歷史數據、資源查找、文件記錄等功能。
元數據中隱藏信息在比賽中是最基本的一種手法,通常用來隱藏一些關鍵的Hint
信息或者是一些重要的如password
等信息。
這類元數據你可以右鍵–>屬性去查看,也可以通過strings
去查看,一般來說,一些隱藏的信息(奇怪的字元串)常常出現在頭部或者尾部。
用法:Strings指令
例子
Breakin-ctf-2017:Mysterious-GIF
要分析這個Gif,我們可以用strings
這指令來查看裡面的所有字符串。
結果我們發現到異常的部分如下:1
2
3
4
5
6GIF89a
!!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~
4d494945767749424144414e42676b71686b6947397730424151454641415343424b6b776767536c41674541416f4942415144644d4e624c3571565769435172
NETSCAPE2.0
ImageMagick
...
這裡的16進制其實是藏在GIF的元數據區裡面。
接下來就是提取,你可以選擇python,但是利用identify
指令顯得更加便捷。1
2
3
4
5
6root in ~/Desktop/tmp λ identify -format "%s %c \n" Question.gif
0 4d494945767749424144414e42676b71686b6947397730424151454641415343424b6b776767536c41674541416f4942415144644d4e624c3571565769435172
1 5832773639712f377933536849507565707478664177525162524f72653330633655772f6f4b3877655a547834346d30414c6f75685634364b63514a6b687271
...
24 484b7735432b667741586c4649746d30396145565458772b787a4c4a623253723667415450574d35715661756278667362356d58482f77443969434c684a536f
25 724b3052485a6b745062457335797444737142486435504646773d3d
用法:identify指令。
而想知道這題的完整做法的人,可以看此Writeup。
Exiftool是一個專門用來讀寫和編輯文件元數據的cmd工具。此工具也支援了非常多的元數據種類,包括了EXIF, GPS, IPTC, XMP, JFIF, GeoTIFF, ICC Profile, Photoshop IRB, FlashPix, AFCP and ID3。當然也可辨認出某些元數據是來自什麼樣的數碼相機如Canon, Casio, DJI, FLIR, FujiFilm, GE, HP, JVC/Victor, Kodak, Leaf, Minolta/Konica-Minolta, Motorola, Nikon, Nintendo, Olympus/Epson, Panasonic/Leica, Pentax/Asahi, Phase One, Reconyx, Ricoh, Samsung, Sanyo, Sigma/Foveon and Sony。
例子:只需輸入exiftool.exe 文件名
,你就可以取得文件的Metadata了。
更多exiftool使用方法和功能可以到以下的鏈接裡面的Documentation學習。
一个GIF文件的結構可分為
下表顯示了一個GIF文件的組成結構:
中間的那個大塊可以被重複任意次。
GIF署名(Signature)和版本號(Version)
GIF署名用來確認一個文件是否是GIF格式的文件,這一部分由三個字元組成:”GIF”;文件版本號也是由三個位元組組成,通常是”87a”或”89a”。
Logical Screen Descriptor(邏輯屏幕描述符)緊跟在header後面。這個塊告訴decoder(解碼器)圖片需要占用的空間。它的大小固定為7個位元組,以canvas width(畫布寬度)和canvas height(畫布高度)開始。
GIF格式可以擁有global color table,或用於針對每個子圖片集,提供local color table。每個color table由一個RGB(就像通常我們見到的(255,0,0)紅色 那種)列表組成。
一個GIF文件一般包含多個圖片。之前的圖片渲染模式一般是將多個圖片繪製到一個大的(virtual canvas)虛擬畫布上,而現在一般將這些圖片集用於實現動畫。
每個image都以一個image descriptor block(圖象描述塊)作為開頭,這個塊固定為10位元組。
終於到了圖片數據實際存儲的地方。Image Data是由一系列的輸出編碼(output codes)構成,它們告訴decoder(解碼器)需要繪製在畫布上的每個顏色信息。這些編碼以位元組碼的形式組織在這個塊中。
該塊為一個單欄位塊,用來指示該數據流的結束。取固定值0x3b。
想完整了解的可看GIF格式圖片詳細解釋
因為GIF是由多幅圖片組合而成,因此要分離GIF成PNG/JPG,我們可以在Linux裡面用convert gif名 圖片名
指令來對GIF做出分離的動作。
而想知道這題的完整做法的人,可以看此Writeup。
利用GIF文件的時間間隔來當成是信息隱藏的載體。
PNG全稱為Protable Network Graphic,屬於無損壓縮位圖圖形格式(lossless data compression)。PNG的出現是為了改善以及替代GIF成為適合在網絡傳輸的圖片格式。此外PNG也具有以下的特色:
首先PNG文件是由一個8字節的PNG文件標識(file signature)域和3個以上的後續數據塊(Chunk)組成。
文件頭89 50 4E 47 0D 0A 1A 0A
+ 數據塊 + 數據塊 + 數據塊…。
十六進制 | 含義 |
---|---|
89 | 用於檢測傳輸系統是否支持8位的字符編碼(8 bit data),用以減少將文本文件被錯誤的識別成PNG文件的機會,反之亦然。 |
50 4E 47 | PNG每個字母對應的ASCII,讓用戶可以使用文本編輯器查看時,識別出是PNG文件。 |
0D 0A | DOS風格的換行符(CRLF)。用於DOS-Unix數據的換行符轉換。 |
1A | 在DOS命令行下,用於阻止文件顯示的文件結束符。 |
0A | Unix風格的換行符(LF)。用於Unix-DOS換行符的轉換。 |
PNG定義了兩種類型的數據塊,一種是稱為關鍵數據塊(critical chunk),這是標準的數據塊,
另一種叫做輔助數據塊(ancillary chunks),這是可選的數據塊。關鍵數據塊定義了4個標準數據塊,每個PNG文件都必須包含它們,PNG讀寫軟件也都必須要支持這些數據塊。
而這些數據塊都由4個部分組成。
|名稱|字節數|說明|
|—–|——|——|
|Length (長度)|4字節|指定数据块中数据域的长度,其长度不超过(231-1)字节|
|Chunk Type Code (數據塊類型碼)|4字節|數據塊類型碼由ASCII字母(A-Z和a-z)組成|
|Chunk Data (數據塊數據)|可變長度|存儲按照Chunk Type Code指定的數據|
|CRC (循環冗餘檢測)|4字節|存儲用來檢測是否有錯誤的循環冗餘碼|
另外,CRC(cyclic redundancy check)域中的值是對Chunk Type Code域和Chunk Data域中的數據進行計算得到的。
文件頭數據塊IHDR(header chunk)包含了儲存的圖像數據基本信息,由13字節組成,而且必須出現在PNG的第一段數據塊內,也只能有一個IHDR。
需要注意的是前8個字節的內容。
|域名稱|字節數|說明|
|—–|——|——|
|Width|4 bytes|圖像寬度,單位是像素|
|Height|4 bytes|圖像高度,單位是像素|
更關於PNG資料可看:
https://www.hackpwn.me/archives/272
1.Outguess
2.http://www.cnblogs.com/pcat/p/6716502.html
1.隐写术个人总结
2.隐写术总结
3.圖片分析
4.世安杯-LSB隐写-png
5.PNG 文檔格式
6.CTF中隐写术一些基础【一】
11月9日更新:
CTF全稱為Capture The Flag,也就是所謂的奪旗賽,起源于1996年DEFCON全球黑客大會,是讓黑客和資安愛好者進行技術競技的一種比賽。
比賽一般上有3種模式。分別是
在解題模式當中,參賽者需要解答出以下類型的題型,每題都會有不一樣的分數,而比賽的最終積分也會決定參賽者的排名。
Reverse Engineering
Web
Cryptography
Forensics
Pwn
Normally, players will specialize in one of these categories. Although it is possible to have a basic knowledge of all of them, we suggest you begin by focusing on the one that interests you most. This guide will be focusing On Binary Exploitation.
若想知道世界各地在什麼時候會舉辦CTF比賽,CTF Times是你可以查詢的地方。這個網站找到一切以前和即將舉行的CTF比賽。當然你也可以找到比賽隊伍的成績,世界排名以及他們提供的答案(Writeup)。
以下是本人推荐新手可以参加的CTF比赛。
當你有了經驗之後,想嘗試高難度的CTF比賽可以試試看做Defcon CTF的題目
每當你做完一道題目的時候,可以把自己的做法和用到的思路寫成Writeup,目的是為了將自己在解題的時候,所學到的知識有系統的整理好,也方便以後可以參考回自己做過類似的題目。
你也可以瀏覽CTF完整資源導航網站來找到更多有關資訊。
第二個推薦的導航網站Got Your Pw。
一些CTF的介紹文章/Wiki/投影片。
而CTF維基則涵蓋了一般的出題思路以及其解題的方式,不管你是新手還是老手都建議你看一看,畢竟基本的一些思路,在這個維基裡面都解釋得非常清楚。此外,想更深入了解維基裡面的每個項目,也可以繼續關注本人的部落格,作者會不定時更新一些對於該維基項目的補充和新的資訊。
除了以上資源,你也可以自己上網閱讀一些大神寫的文章,從他們自我總結的經驗當中,你往往可以學得更快。單單看並不足夠,最重要的還是要自己做筆記,唯有這樣你才會清楚知道自己已經學會了什麼知識。
1.CTF 工具 https://ctf-wiki.github.io/ctf-tools/#!index.md
2.CTF Tools List by Zardus https://github.com/zardus/ctf-tools
3.https://github.com/Gallopsled/pwntools Documentation: https://docs.pwntools.com/en/stable/
4.https://github.com/truongkma/ctf-tools
5.https://github.com/P1kachu/v0lt
6.https://github.com/TUCTF/Tools
7.http://blog.csdn.net/ida0918/article/details/52819147
8.https://github.com/truongkma/ctf-tools
偽隨機數生成器會輸入一個成為種子(Seed)的固定值,然後再通過使用可決定性(Deterministic)的演算法來生成一系列的比特。通常,種子由TRNG生成。通常,如圖所示,存在一些反饋路徑,通過該反饋路徑將算法的一些結果反饋為輸入作為附加輸出位。重要的是要注意的是,輸出比特流完全由輸入值或值確定,以便知道算法和種子的對手可以再現整個比特流。
A PRNG takes as input with a fixed value, called the seed, and produces a sequence of output bits using a deterministic algorithm. Quite often, the seed isgenerated by a TRNG. Typically, as shown, there is some feedback path by which some of the results of the algorithm are fed back as input as additional output bits are produced. The important thing to note is that the output bit stream is determined solely by the input value or values, so that an adversary who knows the algorithm and the seed can reproduce the entire bit stream.
An algorithm that is used to produce an open-ended sequence of bits is referred to as a PRNG. A common application for an open-ended sequence of bits is as input to a symmetric stream cipher, as discussed in Section 8.4. Also, see Figure 4.1a.
Pseudorandom function (PRF): A PRF is used to produce a pseudorandom string of bits of some fixed length. Examples are symmetric encryption keys and nonces. Typically, the PRF takes as input a seed plus some context specific values, such as a user ID or an application ID. A number of examples of PRFswill be seen throughout this book, notably in Chapters 17 and 18.
a true random number generator (TRNG) with two forms of pseudorandom number generators. A TRNG takes as input a source that is
effectively random; the source is often referred to as an entropy source. We discuss such sources in Section 8.6. In essence, the entropy source is drawn from the physical environment of the computer and could include things such as keystroke timing patterns, disk electrical activity, mouse movements, and instantaneous values of the system clock. The source, or combination of sources, serve as input to an algorithm that produces random binary output. The TRNG may simply involve conversion ofan analog source to a binary output. The TRNG may involve additional processing to overcome any bias in the source.
Hard to determine pseudo-random stream if don’t know seed(but know algorithm)
Parameters:
m, the modulus, m > 0
a, the multiplier, 0 < a < m
c, the increment, 0 ≤ c < m
X0, the seed, 0 ≤ X0 < m
Generate sequence of pseudo-random numbers, {Xn}:
Xn+1 = (aXn + c) mod m
Choice of a, c and m is important:
m should be large, prime, e.g. 231 − 1
If c=0, few good values of a, e.g. 75 = 16807
If attacker knows parameters and one number, can easily
determine subsequent numbers
Parameters:
p, q: large prime numbers such that p ≡ q ≡ 3 (mod 4)
n = p × q
s, random number relatively prime to n
Generate sequence of bits, Bi
:
X0 = s
2 mod n
for i = 1 → ∞
Xi = (Xi−1)
2 mod n
Bi = Xi mod 2
Cryptographically secure pseudo-random bit generator
Example Operation of BBS Generator
n = 192649 = 383 × 503, s = 101355
PRNG Mechanisms Based on Block Ciphers
Use symmetric block ciphers (e.g. AES, DES) to produce pseudo-random bits
Seed is encryption key, K, and value V (which is updated)
Cryptographically secure PRNG using Triple DES
Parameters:
64-bit date/time representation, DTi
64-bit seed value, Vi
Pair of 56-bit DES keys, K1 and K2
Operation:
Uses Triple DES three times
(see next slide)
Output:
64-bit pseudo-random number, Ri
64-bit seed value, Vi+1
Encrypt one byte at a time by XOR with pseudo-random byte
Output of generator is called keystream
Important Considerations
Encryption sequence should have large period
Keystream should approximate true random number
stream
Key must withstand brute force attacks
Comparison to Block Ciphers
Stream ciphers often simpler to implement, faster
Block ciphers can re-use keys
Designed by Ron Rivest in 1987
Used in secure web browsing and wireless LANs
Very simple and efficient implementation
Can use variable size key: 8 to 2048 bits
Several theoretical limitations of RC4
No known attacks if use 128-bit key and discard initial values of stream
RC4 is used in WEP (shown to be weak security for wireless LANs)—problem with how keys are used, not RC4 algorithm
Parameters and Variables
Variable length key, K, from 1 to 256 Bytes
State vector, S, 256 Bytes
Temporary vector, T, 256 Bytes
A byte from keystream, k, generated from S
Initial State of S and T
for i = 0 to 255 do
S[i] = i;
T[i] = K[i mod keylen];
Initial Permutation of S
j = 0;
for i = 0 to 255 do
j = (j + S[i] + T[i]) mod 256;
Swap (S[i], S[j]);
序列密碼起源於20世紀20年代的維爾姆(Vernam)密碼。Vernam密碼中的密鑰序列要求是隨機的序列,由於密碼中的密鑰序列的產生、存儲以及分配等方面存在一定的困難,Vernam體制在當時並沒有得到廣泛的應用。然而,在微電子技術和數學理論逐漸變得完善後,序列密碼終於得到了長足的發展和應用。
目前,序列密碼是世界各國的軍事和外交等重要領域中使用的主要密碼體制之一。序列密碼是對稱密碼體制中的一類,又稱為流密碼。
在序列密碼中,明文的每一個位會和密鑰序列的位相加來進行所謂的加密。而序列密碼共有2種:同步序列密碼和異步序列密碼。前者密碼序列取決於密鑰而後者則是密鑰和密文。
要對密文進行加密,我們需要將每一個位置的$x_i$與一個密鑰序列位$s_i$相加後再使用模數2來執行該運算。
明文,密文和密鑰是由獨立的位組成,也可以寫成:$x_i,y_i,s_i∈{0,1}$
加密: $y_i= E s_i(x_i)\equiv x_i + s_i mod 2$
解密: $x_i= D s_i(y_i)\equiv y_i + s_i mod 2$
為什麼加密和解密使用相同函數?
需證明:使用解密函數後,可得回明文位$x_i$。
已知:密文位$y_i$是通過加密函數$y_i\equiv x_i + s_i mod 2$計算得到。
把此加密表達式插入加密函數:
$d s_i\equiv y_i+s_i mod 2$
$\equiv (x_i + s_i)+s_i mod 2$
$x_i + s_i + s_i mod 2$
$x_i + 2s_i mod 2$
$x_i + 0 mod 2$
$x_i mod 2$
Q.E.D
表達式$2s_i mod 2$是0,因為$2\equiv 0 mod 2$。另外,若$s_i$的值為0,此時$2s_i = 2⋅0 \equiv 0 mod 2$。而$s_i$的值為1,此時$2s_i = 2⋅1 =2 \equiv 0 mod 2$。
為什麼可以使用簡單的Mod2加法進行加密?
首先,執行mod2算術運算時,得到的結果只能為0或者1。因此我們可以把mod2的算術運算看成Boolean。
$x_i$ | $s_i$ | $y_i\equiv x_i + s_i mod 2$ |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
其结果和XOR的真值表是一样的。
我們來看一個實際例子:
A 的ASCII數值為65,轉成二進制為1000001。
假設密鑰序列的$s_i$開頭位是0101100。
經過加密後密文為1101101,換回字母是小寫的m。當然如果使用同樣的密鑰解密,那就可以得回明文為A。
也因為這樣所以便可以使用Mod2加法進行加密。
密鑰序列位$s_i$的本質是什麼?
根據以上例子,序列密碼的安全取決於密鑰序列。所以要使到攻擊者難以猜測,那麼序列密碼在加密時就必須使用隨機生成的密鑰序列。
而要生成隨機密鑰序列,可以使用接下來介紹的其中一種隨機數生成器。
現在讓我們來了解到底有哪些的隨機數生成器(RNGs)。
從一個初始種子開始計算來得到序列。以下是其計算方式:
$s_0 = seed$
$s_{x+1}= f(s_i),i=0,1,$
這是其推廣形式,其中t為常數項。
$s_{i+1} = f(s_i,s_{i-1},\ldots s_{i-t})$
例子:線性同餘生成器
$s_0 = seed$
$s_{x + 1} \equiv a{s_i} + b mod m,i = 0,1,\ldots$
ps:持續更新內容當中
]]>Hack with Github在Medium上發布了他們10月份中最受矚目的5大工具和目錄。而所發布的工具以及目錄如下:
List of Awesome Red Team / Red Teaming Resources
This list is for anyone wishing to learn about Red Teaming but do not have a starting point.
Anyway, this is a living resources and will update regularly with latest Adversarial Tactics and Techniques.
You can help by sending Pull Requests to add more information.
A list of Web Security materials and resources for learning the cutting edge penetrating technique.
A curated list of awesome YARA rules, tools, and resources.
A collection of hacking and penetration testing resouces to make you better!
Phishers are still using Internationalized Domain Names to trick users. This project uses computer vision to automatically check if IDNs have a deceptive reading.
以下3個工具是在BlackHat arsenal裡面大放光芒,備受歡迎的。
The tool exploits the common vulnerabilities that caused private keys leakage.
WiFi HID Injector for Fun & Profit
CERTitude is a Python-based tool which aims at assessing the compromised perimeter during incident response assignments. It allows analysts to perform large scale scans of Windows-based information systems by searching for behavioural patterns described in IOC (Indicator Of Compromise) files.
Notable features:
想懂得更多的也可以看看哦。
This repository contains a set of tools and proof of concepts related to PCI-E bus and DMA attacks.
jSQL Injection is a Java application for automatic SQL database injection.
r2 is a rewrite from scratch of radare in order to provide a set of libraries and tools to work with binary files.
Radare project started as a forensics tool, a scriptable commandline hexadecimal editor able to open disk files, but later support for analyzing binaries, disassembling code, debugging programs, attaching to remote gdb servers, ..
This script tests if APs are affected by CVE-2017-13082 (KRACK attack)
During reconnaissance (recon) it is often helpful to get a quick overview of all the relative endpoints in a file. These days web applications have frontend pipelines that make it harder for humans to understand minified code. This tool contains a nifty regular expression to find and extract the relative URLs in such files. This can help surface new targets for security researchers to look at. It can also be used to periodically compare the results of the same file, to see which new endpoints have been deployed. History has shown that this is a goldmine for bug bounty hunters.
]]>CS50- 學習電腦基本知識以及可以學習到C的編程技巧
Second Link: https://www.edx.org/course/introduction-computer-science-harvardx-cs50x
C語言程序設計(The C Programming Language (2nd Edition), Brian W.Kernighan & Dennis M.Ritchie著)
C primer plus
需掌握内容:
滴水逆向第三期培訓 課程內容一覽
小甲魚匯編語言 課程內容一覽
天草逆向資源VIP之50堂課
王爽寫的《汇编语言》(第二版) 附上此書的學習筆記,額外小知識和書裡練習的答案以及其解釋。
Assembly Language for x86 Processors-Pearson KIP R. IRVINE (2014)
額外知識:https://www.pediy.com/kssd/index.html (可以專門看看一些大佬寫的匯編知識以及IA-64體系那系列的文章。)
再來,你就可以進入Linux方面的匯編。
Professional Assembly Language
Assembly language step by step programming with linux
然後,便可以開始學習x64的匯編語言
Windows X64汇编入门(1)
Windows X64汇编入门(2)
Introduction-to-x64-assembly
Moving to x64 深入Windows X64调试 英文版
Introductory Intel x86-X64: Architecture, Assembly, Applications, & Alliteration
需掌握内容:
可延伸路线:學習逆向工程
第三個步驟:學編譯器
推薦課程:Compilers
推薦書本:無
英文版:http://win32assembly.programminghorizon.com/tutorials.html
翻譯版如下:作 者: kanghtta
http://bbs.pediy.com/showthread.php?t=55783
http://bbs.pediy.com/showthread.php?t=55784
http://bbs.pediy.com/showthread.php?t=60320
http://bbs.pediy.com/showthread.php?t=60504
http://bbs.pediy.com/showthread.php?t=60534
http://bbs.pediy.com/showthread.php?t=60591
http://bbs.pediy.com/showthread.php?t=60886
http://bbs.pediy.com/showthread.php?t=60919
http://bbs.pediy.com/showthread.php?t=64082
http://bbs.pediy.com/showthread.php?t=64101
Charles Petzold著的《Windows程序设计》:中文版 英文版。
罗云彬著的《Windows环境下32位汇编语言程序设计》,它以MASM汇编为讲解平台。
【貼心提醒:建議直接看Win32ASMTRK.chm 內含罗云彬 & Iczelion & T$,三位大大的教程】
接下來可以正式學習脫殼有關的課程
推薦書本:加密解密(第三版) & 軟件加密技術內幕
P/s:學習以下課程可以參考上面2本書,來輔助你掌握得更快。
課程綱要
第一课 PE格式
第二课 SEH技術
第三课 認識壳
第四课 常見的壓縮壳和加密壳
第五课 文件類型分析
第六课 尋找OEP
第七课 Dump內存映像
第八课 重建输入表
第九课 手動確定IAT的地址與大小
第十课 DLL文件脫壳
第十一课 優化与自校檢去除
第十二课 ASProtect 2.x壳
和課程有關聯的更多內容:https://bbs.pediy.com/thread-52042.htm
]]>