當前位置:
首頁 > 新聞 > 代碼分析平台CodeQL學習手記(二)

代碼分析平台CodeQL學習手記(二)

在上一篇文章中,我們為讀者介紹了CodeQL平台相關的基本概念,並演示了如何編寫和運行簡單的QL程序。在本文中,我們開始為讀者介紹一些簡單的數據類型,以便為將來的編程工作打好基礎。

基本數據類型及其內建函數

現在,我們開始學習QL語言中的基本數據類型,包括整型、浮點型、日期型、布爾型以及字元串類型。需要注意的是,對於QL語言來說,其支持的數據類型都帶有相應的內建函數——通俗來說,就是系統已經為我們寫好的函數,我們直接拿來就能用了。舉例來說,如果我們想求一個整數的絕對值,直接調用內建函數abs()即可,例如-6.abs()。更一般地說,調用某種類型的變數的通用形式為:直接在變數後面加上一個點號,然後加上要調用的內建函數即可。同時,我們還可以通過點號將多個函數串聯起來,也就是對變數連續進行多種處理,例如,對於一個整型變數a,先求絕對值,再開平方,我們可以將這個處理過程表示為:a.abs().sqrt()。

讀者可能已經發現,在查詢控制台中,當我們在變數後面輸入點號之後,會自動彈出一個含有該類型的變數所有可能的函數列表,這時,我們可以通過滑鼠點選所需的函數,具體如下所示:

另外,當查詢控制台檢測到潛在的語法錯誤後,它會在代碼行號左邊顯示一個紅色的「x」號,或者在相應的字元下面顯示紅色的波浪線。例如,當我們給一個字元串變數賦予一個整數值,並調用絕對值和開平方的函數時,查詢控制台就會給出相應的提示:

字元串類型

字元串類型的變數用來存放以雙引號開頭和結尾的字元序列,即字元串。例如:

from string s

where s = "hello"

select s

其中,在from語句中,我們定義了一個字元串類型的變數s,然後,我們在where語句中,將字元串」hello」賦值給了變數s,最後,我們在select語句中返回變數s的值。如果在查詢控制台運行上述代碼的話,運行結果將為:

hello

注意,上面的運行結果中,並沒有出現雙引號。這是因為,雙引號是一個特殊字元:字元串通常使用雙引號"..."來表示開始和結束,所以雙引號本身不會顯示出來。讀到這裡,讀者可能會問:如果字元串本身恰好包含一個"字元的話,那該怎麼表示呢?這個時候,就該轉義字元\上場了。具體來說,只要在雙引號前面加上一個反斜杠,雙引號就不再表示字元串的開始或結束位置的指示符,而是表示雙引號自身了,具體如下所示:

from string s

where s = "he\"llo"

select s

現在,上述代碼的運行結果會變為:

he"llo

您可能還會問:如果要顯示錶示轉義字元的反斜杠的話,該怎麼辦呢?很簡單,只要在反斜杠的前面再加上一個反斜杠就行了。下面列出的是常見的轉義字元:

n \" 表示字元"

n \\ 表示字元\

n \n 表示換行符

n \r 表示回車符

n \t 表示製表符

同時,QL語言還為字元串類型提供了許多內置的函數,按照官方的說法,就是內置謂詞,例如charAt()函數,該函數可以接收一個表示字元串下標的整型參數,並返回指定下標處的字元。準確來說,該函數的返回值的類型仍然是字元串類型,只不過只包含單個字元而已。請看下面的示例代碼:

from string s

where s = "hello"

select s.charAt(0)

上述代碼的運行結果為:

h

從上面的結果可以看出,字元串元素的下標是從0開始算起的。此外,字元串類型內置的函數有二十多個,這裡就不一一介紹了,具體可以訪問QL的語言規範(https://help.semmle.com/QL/ql-spec/language.html#built-ins-for-string)。

整型與浮點型

簡單來說,整型變數用於保存整數,如306;而浮點型變數則用於保存浮點數,也就是帶小數位的數,如3.14。例如:

from float x, int y

where x = 3.6 and y = 3

select x.pow(y)

就本例來說,上述代碼實際上就是計算3.6的3次方,運行結果為:

同樣的,整型和浮點型也內建了許多函數,例如,abs()函數等,並且,它們的大部分函數的名稱和作用都是相同的,感興趣的讀者可以參閱QL的語言規範(https://help.semmle.com/QL/ql-spec/language.html#built-ins-for-string)。

日期型

下面,我們編寫一個查詢,來計算從今年十月一到2019年12月18日為止已經過去了多少天了,具體如下圖所示:

運行結果如下所示:

需要注意的是,上面代碼中的"01/10/2019"是一個字元串,而函數toDate()是字元串類型的內置函數,其作用是將指定的字元串轉換為日期值。同樣的,日期型也提供了許多內置的函數,如getMonth()函數可以用來提取日期值中的月份部分,具體如下所示:

運行上述代碼後,提取到的月份如下所示:

對於日期型數據來說,除了上面介紹的daysTo()和getMonth()函數外,還有多種函數可以供我們使用,感興趣的讀者可以參閱QL的語言規範(https://help.semmle.com/QL/ql-spec/language.html#built-ins-for-string)。

布爾型

布爾型變數用來存放布爾值,即false(假)或者 true(真)。為了便於讀者理解,這裡舉例說明:

from boolean b

where b = false

select b.booleanNot()

在上面的代碼中,我們定義了一個布爾型變數b,並將其賦值為false,最後返回對變數b進行邏輯非操作後的值。上述代碼的運行結果為:

true

其中,上面的函數booleanNot()的作用,是執行邏輯非運算,也就是取反:真變假,假變真。這裡邏輯變數b原來的值為假(false),取反後,自然就變成真(true)了。接下來,我們再來看看booleanAnd()函數,它能夠用來實現一個邏輯值與另一個(通過參數傳入的)邏輯值的邏輯與運算:

from boolean b

where b = false

select b.booleanAnd(true)

上述代碼的運行結果為:

false

這是因為,只有當兩個邏輯值都為真時,其邏輯與運算的結果才為真。下面,我們再來看看用於實現邏輯或運算的函數,即booleanOr()。下面,我們舉例說明:

from boolean b

where b = false

select b.booleanOr(true)

與上面的函數相似,它也需要傳入一個邏輯值或表達式作為其參數。上述代碼的運行結果為:

true

對於邏輯或運算來說,只要參加運算的值中有一個為真,那麼,其結果就為真。接下來,我們繼續考察用來實現異或運算的函數,即booleanXor()函數,演示代碼如下所示:

from boolean bwhere b = falseselect b.booleanXor(true)

上述示例代碼的運行結果為:

true

這是因為,對於異或運算來說,只要兩個邏輯值不相等,其結果就為真;否則,其結果為假。最後,我們來看一下將邏輯值轉換為字元串的函數:toString()函數,具體代碼如下所示:

運行結果如下所示:

儘管字面上看,與邏輯值中的假值即false是一樣的,但是,實際上它們是完全不同的兩種數據類型——這裡輸出的值是一個字元串。

小結

在上一篇文章中,我們為讀者介紹了CodeQL平台相關的基本概念,並演示了如何編寫和運行簡單的QL程序。在本文中,我們進一步為讀者介紹了一些基本的數據類型。在下一篇文章中,我們將為讀者詳細與代碼分析緊密相關的一些數據類型。

備註:本系列文章乃本人在學習CodeQL平台過程中所做的筆記,希望能夠對大家有點滴幫助——若果真如此的話,本人將備感榮幸。

參考資料:https://help.semmle.com/

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

一次成功利用了相似域的精準BEC攻擊
持續對抗xHunt:通過DNS隧道檢測阻止新型PowerShell後門