1. 程式人生 > >LoadImage載入到系統OEM圖片的BUG解決方案

LoadImage載入到系統OEM圖片的BUG解決方案

簡單說解決方法就是LoadImage第一個引數不要傳遞NULL,而使用GetModuleHandle(NULL)代替。

以下是郵件原文:

Hi,

There is a bug that I get with LoadImage once in a while where it does not 
load the image from the file that I specify but instead loads up a system 
graphic. This only happens very rarely but is annoying when it does. To the 
point where this issue has been annoying me on and off for probably the last 
5 years. I use LoadImage as follows:

hbm = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, m_ddsd.dwWidth, 
m_ddsd.dwHeight, LR_LOADFROMFILE|LR_CREATEDIBSECTION);

Luckily, with the current build of my software is it is finally occurring 
every time giving me a chance to debug this. Below is what I have discovered 
is going wrong with LoadImage and a workaround at the end.

Stepping into the disassembly LoadImage calls the function

[email protected], with 
the first parameter as NULL for the handle to the instance of the module. 
The second parameter is the pointer to the string for the bmp file to open, 
where my string is at address 0x00197fe8, and staying at 0x00197fe8 each time 
at the moment which is why I could debug this.

Below is the disassembly with some of my own comments noting the important 
parts:

[email protected]
:
77D55E95 mov edi,edi 
77D55E97 push ebp 
77D55E98 mov ebp,esp 
77D55E9A sub esp,24h 
77D55E9D mov ecx,dword ptr [ebp+0Ch] ; Copies address of filename 
into ecx
77D55EA0 push ebx 
77D55EA1 push esi 
77D55EA2 mov esi,dword ptr [ebp+8] ; Copies paramater handle to 
instance of module to esi
77D55EA5 push edi 
77D55EA6 xor edi,edi ; Sets edi to zero
77D55EA8 cmp esi,edi ; Checks if parameter handle to instance of 
module is NULL
77D55EAA mov dword ptr [ebp-4],edi 
77D55EAD mov dword ptr [ebp-8],edi 
77D55EB0 je
[email protected]
+21h (77D57C6Eh) ; If esi was NULL jumps 
to code at 77D57C6E
77D55EB6 push dword ptr [ebp+18h] 
77D55EB9 push dword ptr [ebp+14h] 
77D55EBC push dword ptr [ebp+10h] 
77D55EBF push 2 
77D55EC1 push ecx 
77D55EC2 push esi 
77D55EC3 call [email protected] (77D5298Dh) ; This is what 
we want it to call 


The two important parts above are:
1. The code at 77D55E9D. Which copies the address of the bmp file string 
into ecx.

2. The code at 77D55EA8. This checks if the hinst parameter passed into 
LoadImage is NULL. If we jump to the code at address 77D57C6E becuase of this 
line:

77D55EB0 je [email protected]+21h (77D57C6Eh) ; If esi was NULL jumps 
to code at 77D57C6E


This takes us to this assembly:

77D57C6E mov esi,dword ptr [_hmodUser (77DA0264h)] 
77D57C74 movzx eax,cx 
77D57C77 xor ebx,ebx 
77D57C79 sub eax,7FDCh 
77D57C7E mov dword ptr [ebp+0Ch],edi 
77D57C81 mov dword ptr [ebp+8],edi 
77D57C84 je 77D745B6 
77D57C8A sub eax,16h 
77D57C8D je [email protected]+141h (77D74471h) 
77D57C93 sub eax,0Dh 
77D57C96 je [email protected]+128h (77D74458h) 
77D57C9C xor eax,eax 
77D57C9E cmp cx,7FE2h 
77D57CA3 sete al 
77D57CA6 mov edx,77D41A98h ;edx is set here to address 77D41A98h 
77D57CAB mov dword ptr [ebp-0Ch],eax 
77D57CAE xor eax,eax 
77D57CB0 cmp cx,7FF7h 
77D57CB5 sete al 
77D57CB8 mov dword ptr [ebp-10h],eax 
77D57CBB xor eax,eax ; sets eax to zero
77D57CBD cmp word ptr [edx],cx ; cx is the lower 16 bits of the 
filename addesss
77D57CC0 je [email protected]+81h (77D57CCEh) ; jumps if cx equals 
address in edx
77D57CC2 add edx,6 ; edx += 6
77D57CC5 inc eax ; eax++
77D57CC6 cmp edx,offset _gwszShellFont2 (77D41B58h) ; checks if end 
loop
77D57CCC jl [email protected]+70h (77D57CBDh) 
77D57CCE cmp eax,20h ; if we looped around 0x20 
77D57CD1 je 77D55EB6 ; times then jumps back to 77D55EB6


The loop at the end is important part, and is what causes the issue. I will 
step through the important parts:

The register edx is set to the value 77D41A98. 

77D57CA6 mov edx,77D41A98h 

Here is the loop:
77D57CC6 cmp edx,offset _gwszShellFont2 (77D41B58h) ;
77D57CCC jl [email protected]+70h (77D57CBDh) ; 

This keeps looping around back to 77D57CBD while edx is less than the value 
77D41B58. Incrementing edx by 6 each time. So the following calculation:
0x77D41B58 - 0x77D41A98 = 0xC0 / 6 = 0x20

Means the max eax can equal is 0x20. This is important because the next two 
lines after the loop are:
77D57CCE cmp eax,20h ; if we looped around 0x20 
77D57CD1 je 77D55EB6 ; times then jumps back to 77D55EB6

This is what we want as that way it jumps back to the code at 77D55EB6 which 
is the first lot of assembly code, and then continues down to the line: 
77D55EC3 call [email protected] (77D5298Dh)

Which loads the bmp from the file, and all is good.

Now the issue is at the the line the loop keeps jumping to:
77D57CBD cmp word ptr [edx],cx 

ecx is where the address of the bmps filename is stored shown earlier. 
However, this line uses the register cx which is the lower 16 bits of the 
address. And it is checking to see if it matches a value at the address of 
edx which is being incremented each time through the loop. As my string is 
at address 0x00197fe8 it is therefore checking if 0x7fe8 is in the list in 
memory between 0x77D41A98 and 0x77D41B58, this is the list of OEM images. In 
my case it gets a match when eax equals 16, and leaves the loop. It then 
continues down through the code to:
77D57D56 call [email protected] (77D52723h) 

Which then creates the OEM image instead of giving loading the bitmap I 
specified. 

The above loop shows why it is rare to get the wrong image. As the bottom 
16 bits of the filenames address has to match an OEM's ID for it to occur.

The following code will replicate this issue:
HBITMAP hbm = 0;
hbm = (HBITMAP)LoadImage(NULL, (TCHAR*)0x00197fe8, IMAGE_BITMAP, 0, 0, 
LR_LOADFROMFILE|LR_CREATEDIBSECTION);

If you use this code you will find you get a handle to a bitmap even though 
you have given an address which will have random data in it. This is because 
it will never try use access this address, but will just use the 0x7fe8 part 
of it as it happens to match and OEM image ID.


The fix for this when loading from a file is to always pass 
'GetModuleHandle(0)' as the first parameter to LoadImage. Even though the 
documentation states:
hinst - [in] Handle to an instance of the module that contains the image to 
be loaded.

This is because of the following in the first lot of assembly I posted is:
77D55EA2 mov esi,dword ptr [ebp+8] 

This copies the handle to instance of module into esi. 

It then checks if this is zero with the following code:
77D55EA6 xor edi,edi ; Sets edi to zero
77D55EA8 cmp esi,edi ; Checks if parameter handle to instance of 
module NULL

If it is not NULL then it does not do the next lot of assembly which checks 
if the lower 16 bits of your address matches an OEM image.

So the the verdict is if you are loading a bmp from a file you should always 
pass the first parameter to LoadImage, till this issue is fixed ( if ever ).

My problem is the case where I am currently experiencing this bug I am not 
actually calling LoadImage directly, but calling the DirectX function 
'D3DXLoadTextureFromFile' which ends up calling LoadImage internally, passing 
NULL as the first parameter.

I guess I will have to go back to LoadImage for loading bmps into DirectX, 
and replicate the extra couple of features 'D3DXLoadTextureFromFile' provides 
that I use. 

Adam Dokter

相關推薦

LoadImage載入系統OEM圖片BUG解決方案

簡單說解決方法就是LoadImage第一個引數不要傳遞NULL,而使用GetModuleHandle(NULL)代替。 以下是郵件原文: Hi,There is a bug that I get with LoadImage once in a while where i

移動端常見自適應圖片載入時頁面塌陷問題解決方案

<style> .box{ width:100%; height:0; overflow:hidden; padding-bottom:24.6%; } img{ width:100%; } </style> <div class="box"&

大多數圖片Uri無法獲取檔案的bug解決方案

昨天公司前段找到自己問Android的內嵌頁<type="file">上傳有問題,公司之前的內嵌頁為了方便開發用了一個第三方的庫agentweb自己測試了下發現6.0的手機可以,但7.0及之上的不能上傳,於是升級了一一該庫的依賴到最新版本com.just.agen

java系統高並發解決方案(轉載收藏)

說我 操作 動態 love 基礎上 iter() 差異 puts distrib 一個小型的網站,比如個人網站,可以使用最簡單的html靜態頁面就實現了,配合一些圖片達到美化效果,所有的頁面均存放在一個目錄下,這樣的網站對系統架構、性能的要求都很簡單,隨著互聯網業務的不斷豐

電腦USB鍵盤鼠標無法使用,重裝系統後 問題依舊 解決方案

使用 ati 開機 解決 hci 恢復 軟件 mode 裝系統 解決方案 1、開機進入BIOS; 2、Advanced選項--》USB Configuration--》XHCI Pre-Boot Mode 關閉; 3、F10保存退出,重啟 這種方法雖然能夠使USB恢復使用,

CC2540是一款高性價比,低功耗片上系統(Soc)解決方案,它適合藍牙低功耗應用領域

數字 醫療 保持 國內 定時 技術 定位 集成電路 性能 CC2540是一款高性價比,低功耗片上系統(Soc)解決方案,它適合藍牙低功耗應用領域,極少的外圍元器件以及強大網絡節點建立成為可能。CC2540是一款含有高速和低功耗8051內核的RF收發器。適用於低功耗系統,有超

Ext Js 6.2.1 classic grid 滾動條bug解決方案

efi 父類 滾動 cti seq position column spa 元素 此bug未在其他版本發現,參考高版本代碼重寫類解決此bug,直接上代碼: 1 /** 2 * 如果列表同時存在橫向滾動條和豎向滾動條,當豎向滾動條滾動到底部時 3 * 點擊

[golang] Glide 包管理工具,在windows10 64位系統上的bug修復方案

環境 all 管理工具 oos for 討論 pos inb direct bug重現 [ERROR] Unable to export dependencies to vendor directory: Error moving files: exit status 1

機械制造行業生產ERP管理系統主要需求及解決方案

機械制造erp 機械設備erp 生產erp 眾所周知,機械制造行業是國民經濟增長的重要支撐,隨著信息化的發展,機械制造企業面臨各種挑戰,頻繁出現部門監管力度不夠、生產計劃難定,產品質量不過關、生產過程操作不規範以及原材料使用不當造成資源浪等現象。面對這些問題,單純依靠傳統的管理方式,顯然已經滿足不

vue中使用baidushare分享到微信無法顯示bug解決方案

解決 需要 基礎知識 才會 微信 在線 項目 fig 二維 最近vue單頁面項目中有個頁面分享的功能需求,按以往經驗,選擇了百度開源的baidushare.js 經過一天的掙紮,終於弄清楚了分享到微信後無法顯示的原因。 對比分析:   以往成功使用:另寫了一個專門的分

Zabbix企業級分布式系統網絡監視解決方案實戰課程

discover 解決方案 res image discovery process RoCE gen 第一課 ------------------課程目錄------------------- 1.[zabbix企業實戰]1.top1.mp42.top2.mp43.top

Mysql 安裝bug解決方案與一般使用指令

href ges 發現 img 導致 工作 start 技術 安裝 問題描述: 在安裝mysql 時,如果第一次沒安裝成功,第二次重裝可能出現莫名奇妙的情況。通過一番嘗試,發現,安裝往上的教程還是無法成功安裝的主要原因是第一次安裝雖然未成功,但是mysql 默認的3306端

VMWare 14.1 15 Pro 安裝 macOS Mojave 10.14.1系統 遇到的問題解決方案

    安裝環境WIN10VMware Workstation Pro 15.0.0 Build 10134415工具準備1.VMware Workstation Pro 15.0.0 Build 10134415官網下載地址:http://download3.vmware.com/s

製造業MES系統需求分析及解決方案

MES系統面向生產管理人員,滿足排產、排程,瞭解整體生產資訊的需求,支援線上生產資訊廣播,提供廠內精益物料管理,物料拉動,生產質量管控。排產和跟蹤系統制定上線順序,並下發到車間控制PLC裡負責執行。MES生成系統內部訂單數量範圍內的計劃,所以MES不用關心,由於生產模式造成的插單問題(上次訂單未生產完成,造成

制造業MES系統需求分析及解決方案

及其 情況 系統架構 看板 分類 生產訂單 活性 軟件源代碼 一周 MES系統面向生產管理人員,滿足排產、調度,了解整體生產信息的需求,支持在線生產信息廣播,提供廠內精益物料管理,物料拉動,生產質量管控。排產和跟蹤系統制定上線順序,並下發到車間控制PLC裏負責執行。MES生

Linux 系統出現電流音解決方案

dex spa 性能 導致 資料 target lin evel eve 迫於Windows 系統最近的各種故障,今天脫坑換了openSUSE Linux ,在上網途中播放視頻時偶爾會出現電流音,雖然影響不大,但是還是進行了一些排查。 通過觀察電流音出現時的系統負載的波段,

關於手機端input獲取焦點呼起鍵盤背景圖片擠壓解決方案

1、解決圖片擠壓問題 可以將背景圖片height: 100%改為min-height:100%即可 2、解決android下鍵盤不遮擋input輸入框 // 處理android 下鍵盤遮擋input let ua = window.navigator.userAgent

微信小程式——Feed流圖片佈局解決方案

三種Feed流中的圖片佈局:宮格式佈局、拼圖式佈局、瀑布流式佈局。 一、宮格式佈局 宮格式佈局也就是九宮格佈局,多用在社交類的APP中,九宮格圖片不僅能放進去很多內容,同時也能很好地引起網友的關注。          從上面

@ResponseBody跨系統請求中文亂碼解決方案

一.原因 spring mvc的一個bug,spring MVC有一系列HttpMessageConverter去處理用@ResponseBody註解的返回值,如返回list則使用MappingJacksonHttpMessageConverter,返回string,則使用StringHttpM

安卓開發網路相關bug解決方案

兩個bug: 1: android.os.NetworkOnMainThreadException 原因:因為main執行緒要處理UI,預設不能使用網路導致假死 Android這個設計是為了防止網路請求時間過長而導致介面假死的情況發生。解決方案有兩個,一個是使用StrictMode,二是使用