<var id="9nznz"></var>
<del id="9nznz"></del>
<ins id="9nznz"></ins>
<cite id="9nznz"><span id="9nznz"></span></cite>
<ins id="9nznz"><noframes id="9nznz">
<ins id="9nznz"><noframes id="9nznz"><ins id="9nznz"></ins>
登錄賬號    免費注冊    關于我們    操作指南    常用工具     設為首頁    加入收藏    聯系我們
    網站首頁  ▲官方微信    ▲官方博客    ▲官方微博

 綜合搜索

 站內搜索
    當前位置:計算機教程 > 操作系統 > 正文閱讀


一款軟件的亂碼處理 - 看二位高手的不同解決方案


媒體:原創  作者:佚名
專業號:真逗  2010/1/11 22:44:28 發布


問題文件

wanfu的問題:

我漢化了一款VC軟件,該軟件有標準資源和Uncode和ASCII非標字符,我已修改了所有標準資源中的字體和語系為簡體中文,但是修改主程序中的ASCII非標字符為簡體中文時,結果在“驗證”的列表框中顯示亂碼。我試圖改為UFT-8和Uncode也沒有成功。試圖用OllyDBG修改,只找到與字體設置相關的CreateFontW模塊,字符設置 CharSet = DEFAULT_CHARSET 應該不用改。

哪位高手可以幫助我?

問題所在

cao_cong的答復:

你這個是程序的轉碼問題。比如你漢化的驗證列表框中的第一個“添加“<%s>”標記將改變文檔“%s”的格式和/或結構?!?,ASCII碼是
CCEDBCD3A1B03C25733EA1B1B1EABCC7BDABB8C4B1E4CEC4B5B5A1B02573A1B1B5C4B8F1CABDBACD2FBBF2BDE1B9B9A1A3,
程序轉換成MultiByte,成為CC00ED00BC00D300A100B0003C00250073003E00A100B100B100EA00BC00C700BD00AB00B800C400B100E400CE00C400B50
0B500A100B00025007300A100B100B500C400B800F100CA00BD00BA00CD002F00BB00F200BD00E100B900B900A100A300,
而最后顯示的應該是UNICODE,對應你的翻譯最后應該顯示的是UNICODE編碼FB6DA0521C203C00250073003E001D200768B08B065C3965D853876563681C20250073001D2084763C680F5F8C542F001662D
37E84670230,可程序沒干這事,給你轉換成MultiByte它就完事了。所以你英文顯示正常,變成中文寬字符時肯定不正常了。
貌似除了在程序中寫轉換字符的補丁代碼外沒啥更好的方法。貼個效果圖:
弄起來應該也比較麻煩。我有空的話就幫你搞一下,也對你那個老蓋的工具比較感興趣,想瞅瞅


解決方案

restools的解決方案(1)

匯編不在行,所以打洞放代碼的功夫就留待高人來實現了,我的方法很簡單,作了個DLL,里面有個函數,然后讓軟件的處理變成調用我的DLL來處理。我還是喜歡這種方式,因為我不需要在軟件中尋找合適位置放置合適代碼,而且這需要很強的ASM代碼整合能力,一不小心,可能引起異常(這里花的時間絕對不會少)。

雖然這不是完美的實現方法,但是對于漢化這樣的工程,如果不是為了技術探討,大可不必做到非常完美,只需要實現效果即可。

DLL做出來了,用來參考,可把里面反匯編的代碼稍作修改應該可以在原程序上放置實現更完美的效果。

附加文件
附加文件  LM.rar ( 73.28k ) 下載次數: 25



cao_cong
的解決方案

再來一個打過補丁的。本來想用LordPE直接添加程序中沒有的函數WideCharToMultiByte和SendMessageA的,看了一下程序中有LoadLibraryA和GetProcAddress這兩個函數,想想還是用這兩個函數來獲取WideCharToMultiByte和SendMessageA函數地址吧。因為調用的都是系統函數,我就不考慮用FreeLibrary來釋放了。原本想直接抄restools兄的DLL文件中的代碼來補丁的,不過堆棧平衡實在不大好處理,反而耗了我很多時間。最后干脆直接寫了。我在程序的最后添加了一個大小為400H的區段用來寫代碼,主要是在程序中找不到夠寫代碼的空間了。
貼上用于OllyDBG的寫補丁代碼插件NonaWrite的代碼,我在里面都加了注釋,應該容易理解。在程序中添加一個區段后就可以用OD載入,再用NonaWrite插件把這些代碼直接寫到程序中保存就行了:

變量:
;temp1:用來存放用GetProcAddress獲取的WideCharToMultiByte函數地址。
;偏移:00039639,VA:0043B039

;temp2:用來存放用GetProcAddress獲取的SendMessageA函數地址。
;偏移:0003963E,VA:0043B03E

;temp3:用來保存調用SendMessageW時的句柄。
;偏移:00039643,VA:0043B043

;temp4:用來保存要轉換的字串地址。
;偏移:00039648,VA:0043B048

;temp5:分配200字節用來作為轉換字串的緩沖區
;偏移:00039660,VA:0043B060
;結束偏移:00039860,VA:0043B260

;常量:
;const1:用來存放字串KERNEL32.dll。
;偏移:39600,RVA:00032C70,VA:0043B000

;const2:用來存放字串WideCharToMultiByte。
;偏移:3960D,VA:0043B00D

;const3:用來存放字串USER32.dll。
;偏移:39621,VA:0043B021

;const4:用來存放字串SendMessageA。
;偏移:3962C,VA:0043B02C

;其他:
;LoadLibraryA:
;VA:40105C

;GetProcAddress:
;VA:401060

;原程序中還要在418508處改一下:
;0x418508:
;call 43B270                              ;改成這個

;補丁代碼:開始地址為0043B270
;獲取WideCharToMultiByte和SendMessageA函數:
0x43B270:
pushad
mov eax,[esp 24]                      ;temp3,保存前面修改SendMessageW時的句柄
mov dword ptr [0043B043],eax
mov eax,[esp 30]                      ;temp4,保存要轉換的字串地址
mov dword ptr [0043B048],eax
cmp dword ptr [0043B039],0      ;判斷是否已獲取了要用的函數
jnz 43B2ab                                ;out1
push 0043B000                         ;const1
call dword ptr[40105C]               ;調用LoadLibraryA
push 0043B00D                         ;const2
push eax
call dword ptr[401060]               ;調用GetProcAddress
mov dword ptr [0043B039],eax   ;保存WideCharToMultiByte函數地址到temp1
;out1
cmp dword ptr [0043B03E],0
jnz 43B2d1                               ;out2
push 0043B021                         ;const3
call dword ptr[40105C]               ;調用LoadLibraryA
push 0043B02C                         ;const4
push eax
call dword ptr[401060]               ;調用GetProcAddress
mov dword ptr [0043B03E],eax   ;保存SendMessageA函數地址到temp2
;out2,開始轉換
push    0                                  ; lpUsedDefaultChar
push    0                                  ; lpDefaultChar
push    200                               ; cchMultiByte
push    0043B060                      ; temp5,lpMultiByteStr
push    -1                                 ; cchWideChar
push    dword ptr [0043B048]     ; temp4,lpWideCharStr
push    0                                  ; dwFlags
push    4E4                               ; CodePage
call    dword ptr[0043B039]         ;調用WideCharToMultiByte
mov    eax,0043B060
push    eax                               ; lParam
push    0                                  ; wParam
push    180                               ; Message = LB_ADDSTRING
push    dword ptr [0043B043]     ; hWnd
call    dword ptr[0043B03E]        ;調用SendMessageA
popad
ret 10

 附件是修改過的主程序:
附加文件  LOOMConfig.rar ( 72.46k ) 下載次數: 4

 restools的解決方案(2)

既然cc兄作了相當完美的解決方案出來,那我就借用一下,再把它處理的完善已點,以下的修改

;變量:
;首先,文件沒有擴展任何實際大小,所有代碼,常量都在文件的空隙中存放,至于變量,大部分使用的是虛的空間。這樣做是因為文件實際上是沒有足夠實際空間的。
;先把文件的text段虛擬大小用盡也就是2F00,這不影響原來的程序結構的,據測試,好像改不改都可以用,不過還是按規矩修改了
;再把文件的data段虛擬大小用盡也就是3000,這不影響原來的程序結構的,據測試,好像改不改都可以用,不過還是按規矩修改了
;開放text的寫入功能,使變量可以寫入

;temp1:用來存放用GetProcAddress獲取的WideCharToMultiByte函數地址。 ---把text段虛擬空間擴展到2F000,變量運行時放到虛的位置,就是文件中并不存在的位置
;VA:42FE28

;temp2:用來存放用GetProcAddress獲取的SendMessageA函數地址。---同上
;VA:42FE2E

;temp3:用來保存調用SendMessageW時的句柄。---同上
;VA:42FE34

;temp4:用來保存要轉換的字串地址。---同上
;VA:42FE3A

;temp5:分配190字節用來作為轉換字串的緩沖區 ---放到 Data 段空閑位置,大部分是虛的,文件沒有實位置
;VA:432E60 --使用靠在后面擴展的虛擬空間,因為這個段大多數會有數據寫入,前面已經分配的虛擬空間不太安全
;0x190 就是 400 個字節,對于這個程序,我想應該足夠了

;常量:
;const1:用來存放字串KERNEL32.dll。---------------------------原程序已有該字串,借用,省去空間
;VA:42F602

;const2:用來存放字串WideCharToMultiByte。---放到 text 段空閑位置 ,文件實位置
;VA:42FDE0

;const3:用來存放字串USER32.dll。---------------------------原程序已有該字串,借用,省去空間
;VA:42F6D4

;const4:用來存放字串SendMessageA。---放到 text 段空閑位置 ,文件實位置
;VA:42FDF4

;其他:
;LoadLibraryA:
;VA:40105C

;GetProcAddress:
;VA:401060

;原程序中還要在418508處改一下:
;0x418508:
;call 42FD3E                            ;改成這個

;補丁代碼:開始地址為0042FD3E
;獲取WideCharToMultiByte和SendMessageA函數:
0x42FD3E:
pushad
mov eax,[esp 24]                    ;temp3,保存前面修改SendMessageW時的句柄, ListBox 句柄
mov dword ptr [42FE34],eax
mov eax,[esp 30]                    ;temp4,保存要轉換的字串地址, 錯誤字符串的地址,準備用來修復
mov dword ptr [42FE3A],eax
cmp dword ptr [42FE28],0            ;temp1,WideCharToMultiByte判斷是否已獲取了要用的函數,如果有跳轉,不再獲取
jnz 42FD7C                          ;out1
push 42F602                         ;const1
call dword ptr[40105C]              ;調用LoadLibraryA
push 42FDE0                         ;const2
push eax
call dword ptr[401060]              ;調用GetProcAddress
mov dword ptr [42FE28],eax          ;保存WideCharToMultiByte函數地址到 temp1
;out1
cmp dword ptr [42FE2E],0            ;temp2,判斷是否已獲取了要用的函數,如果有跳轉,不再獲取
jnz 43FDA2                          ;out2
push 42F6D4                         ;const3,字串USER32.dll
call dword ptr[40105C]              ;調用LoadLibraryA
push 42FDF4                         ;const4,字串SendMessageA
push eax
call dword ptr[401060]              ;調用GetProcAddress
mov dword ptr [42FE2E],eax          ;保存SendMessageA函數地址到temp2
;out2,開始轉換
push    0                        ; lpUsedDefaultChar
push    0                        ; lpDefaultChar
push    190                         ; cchMultiByte
push    432E60                      ; temp5,lpMultiByteStr
push    -1                          ; cchWideChar
push    dword ptr [42FE3A]          ; temp4,lpWideCharStr
push    0                        ; dwFlags
push    4E4                         ; CodePage
call    dword ptr[42FE28]        ; temp1,調用WideCharToMultiByte
mov    eax,432E60                ; 輸出正確的 ANSI 字符串
push    eax                         ; lParam
push    0                        ; wParam
push    180                         ; Message = LB_ADDSTRING
push    dword ptr [42FE34]          ; temp3,hWnd
call    dword ptr [42FE2E]          ; 調用SendMessageA
popad
ret 10

文件沒增加一個字節,資源段仍然處在最后位置,可以用資源編輯工具繼續編輯而無需擔心。

媒體:原創  作者:佚名
專業號:真逗  2010/1/11 22:44:28 發布
0

我也說兩句
E-File帳號:用戶名: 密碼: [注冊]
評論:(內容不能超過500字,如果您不填寫用戶名和密碼只能以游客的身份發表評論。)

*評論內容將在30分鐘以后顯示!
版權聲明:
1.依據《服務條款》,本網頁發布的原創作品,版權歸發布者(即注冊用戶)所有;本網頁發布的轉載作品,由發布者按照互聯網精神進行分享,遵守相關法律法規,無商業獲利行為,無版權糾紛。
2.本網頁是第三方信息存儲空間,阿酷公司是網絡服務提供者,服務對象為注冊用戶。該項服務免費,阿酷公司不向注冊用戶收取任何費用。
  名稱:阿酷(北京)科技發展有限公司
  聯系人:李女士,QQ468780427
  網絡地址:www.arkoo.com
3.本網頁參與各方的所有行為,完全遵守《信息網絡傳播權保護條例》。如有侵權行為,請權利人通知阿酷公司,阿酷公司將根據本條例第二十二條規定刪除侵權作品。

 

  
宇翔微機外語學校

學員的成績是廣告

    熱點文章
專業號:真逗


真逗的最新文章:
Copyright (C) 1998-2024 版權所有 宇翔微機外語學校 All rights reserved  2014年12月1日改版  后臺管理
總校地址:黑龍江省鐵力市火車站前林業局團結路 122 號 2 樓(宇翔大街南、松濤道口路西)(原火車站前停車場北老管開發樓2樓遷此)
電話:0458-2387012  13504572966  E-mail:  yxwjwyxx@163.com    QQ:394035028    QQ:710002157
技術支持:北京宇翔盛文國際科貿有限公司技術部    QQ:767876168    E-Mail:  hljtlyx@163.com
          基于 E-file 技術構建 黑ICP備08003350號
WWW.1068X.COM