乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      批處理技術內(nèi)幕:Unicode | Demon's Blog

       ar135 2016-06-15

      標題: 批處理技術內(nèi)幕:Unicode
      作者: Demon
      鏈接: http:///reverse/cmd-internal-unicode.html
      版權: 本博客的所有文章,都遵守“署名-非商業(yè)性使用-相同方式共享 2.5 中國大陸”協(xié)議條款。

      CMD在內(nèi)部是以Unicode來運作的,這點無須置疑。你可能要問,如果是Unicode的話,那么Unicode編碼保存的腳本怎么不能執(zhí)行?

      讓我們一起來看一下CMD是怎么解析批處理腳本的吧。

      echo http://

      用OllyDbg載入,bp ReadFile后運行,就會斷在讀取腳本的地方。

      ReadFile

      可以看到每次讀取0x1FFF(8191)個字節(jié)(注意不是字符)到緩沖區(qū)。

      F8單步,不一會就到了MultiByteToWideChar函數(shù),將剛才讀取的字節(jié)以當前代碼頁轉(zhuǎn)換成Unicode儲存在另一個緩沖區(qū),之后的處理都是建立在轉(zhuǎn)換后的Unicode之上的。

      MultiByteToWideChar

      也就是說,CMD在讀取腳本時并不會預先判斷腳本的編碼(實際上,要準確判斷文件編碼幾乎是不可能的),而是調(diào)用ReadFile函數(shù)讀取文件后以當前代碼頁調(diào)用MultiByteToWideChar函數(shù)將其轉(zhuǎn)成Unicode編碼。如果你的是簡體中文系統(tǒng),而你沒有修改默認的區(qū)域設置,并且你沒有在批處理中使用chcp命令的話,那么默認的當前代碼頁就是936,即GBK編碼。

      就算你的批處理是使用Unicode保存的,CMD也不會知道,CMD仍然傻傻的把它當成GBK,Unicode被當成GBK轉(zhuǎn)換成Unicode,結果當然是不能運行的。

      到這里還沒有結束,我們都知道CMD有一個/U開關,幫助文檔對/U的描述是:

      Causes the output of internal commands to a pipe or file to be Unicode

      對應的還有一個/A開關:

      Causes the output of internal commands to a pipe or file to be ANSI

      默認是開關是/A,也就是說CMD命令輸出的默認編碼是ANSI。

      等一下,好像哪里不對吧?是的,只有在輸出被重定向到管道或者文件的時候才是ANSI(默認,不加/U的話),換句話說,如果直接在CMD輸出,那么仍然是Unicode編碼。

      echo 你好,世界
      echo 你好,世界>1.txt

      CMD對這兩行代碼的處理是不一樣的。

      FileIsConsole

      如果標準輸出STDOUT沒有被重定向(第一行代碼),那么直接調(diào)用WriteConsoleW函數(shù)輸出Unicode。

      WriteConsole

      如果標準輸出STDOUT被重定向了(第二行代碼),那么會先以當前代碼頁為參數(shù)調(diào)用WideCharToMultiByte函數(shù)將Unicode轉(zhuǎn)成相應的編碼,再調(diào)用WriteFile寫入文件。

      WriteFile

      請注意我一直強調(diào)當前代碼頁,因為代碼頁是可以通過chcp命令改變的,所以從MultiByteToWideChar到WideCharToMultiByte這段時間里,當前的代碼頁很可能被改變了。

      猜猜看下面這段批處理會輸出什么?

      @echo off
      setlocal enabledelayedexpansion
      chcp 437>nul
      set c=個
      chcp 1252>nul
      echo !c!>1.txt
      pause

      為了減低難度,給出兩個鏈接:

      http://en./wiki/Code_page_437

      http://en./wiki/Windows-1252

      如果你不用運行就能知道答案,那么恭喜你已經(jīng)理解本文了;如果你就算實際運行了還是想不明白為什么,那也不用灰心,我會告訴你答案。

      前兩行大家都懂,我就不說了,第三行chcp將當前活動的代碼頁改為437,CMD就會把之后的代碼當成437編碼(請允許我這么稱呼,因為我實在不知道它叫什么編碼)。

      好在437編碼是部分兼容ASCII的,所以"set c="并不會有什么問題,它仍然是"set c=";但是437里面是沒有"個"這個中文字符的,它會把"個"當成0x82和0x80兩個字符,而437中的0x82和0x80對應Unicode中的0x00E9和0x00C7(上面的鏈接里有映射表),于是

      set c=個

      這行代碼運行之后c在內(nèi)存中的值是0x00E9 0x00C7。

      接下來chcp將代碼頁改成了1252,而下一行echo是把c的值重定向輸出到1.txt,所以要把Unicode轉(zhuǎn)成1252編碼。0x00E9對應1252中的0xE9,0x00C7對應1252中的0xC7(參考上面的鏈接),所以轉(zhuǎn)換以后的值是0xE9 0xC7,即1.txt的內(nèi)容為0xE9 0xC7(當然,還有echo附加上去的0x0D 0x0A)。

      用記事本打開1.txt時當前的代碼頁仍然是936不變,所以將按照GBK編碼來解釋0xE9 0xC7,這正好是"榍"字的GBK碼,怎么樣,是不是繞暈了?

      如果你還是搞不明白,那也沒關系,你只要知道CMD會先把批處理腳本轉(zhuǎn)成Unicode再進行解析的就行了;如果你搞懂了,那可以考慮一下下面的代碼會生成什么:

      chcp 37
      in[

      可以參考http://en./wiki/EBCDIC_037

      隨機文章:

      1. MySQL整數(shù)類型TINYINT SMALLINT MEDIUMINT INT BIGINT
      2. MySQL快速插入大量數(shù)據(jù)——使用LOAD DATA語句
      3. 隱藏系統(tǒng)托盤圖標的小程序TrayHider
      4. 那些長的像UTF-8的GBK編碼
      5. 迅雷高速通道與離線下載

      這篇文章發(fā)布于 2012年07月25日,星期三,13:52,歸類于 逆向調(diào)試。 您可以跟蹤這篇文章的評論通過 RSS 2.0 feed。 您可以留下評論,或者從您的站點trackback。             

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多