接續前面2篇網樂通Scanner Server文章,
這篇開始,會將我針對HP Color LaserJet CM1015掃描功能的Close Code解析,
因為目前尚未破解,所以這系列會不會有完結篇不確定,
解析到哪,又剛好有空、有興趣,就po到哪。
背景資訊:
HP Color LaserJet CM1015這台HP事務機功能如下:
- USB介面
- 有彩色掃描功能
- 有彩色列印功能
- 是雷射列印
- 黑白、彩色掃描
- 黑白、彩色列印
- 印表機狀態資訊
HP Color LaserJet cm1015 Multifunction Printer
而根據HPLIP 2.8.10的Release時間回推,這台應該是在2008年的款式,
我的購買時間我已經忘了。
HPLIP本身雖然是OpenSource的專案,但HP並沒有將全部的檔案都OpenSource,
HPLIP在大部分機種上要求要安裝Driver Plugin,
這個Driver Plugin提供了這些機種需要的Close Code Library,
它們包括:
- bb_marvell-x86_32.so
- bb_marvell-x86_64.so
- bb_soapht-x86_32.so
- bb_soapht-x86_64.so
- bb_soap-x86_32.so
- bb_soap-x86_64.so
- fax_marvell-x86_32.so
- fax_marvell-x86_64.so
- hbpl1-x86_32.so
- hbpl1-x86_64.so
- lj-x86_32.so
- lj-x86_64.so
從程式碼看起來,
HP不同機種使用了不同的Protocol,不同Protocol使用不同的Close Code Library檔案,
CM1015的Protocol看起來只是單純的SOAP,使用的是bb_soap。
怎麼知道是用bb_soap?
因為我在網樂通上手動把Driver Plugin放上去,執行scanimage後,
在/var/log/syslog出現類似如下:
scanimage: common/utils.c 188: unable to load library /usr/local/hplip/share/hplip/scan/plugins/bb_soap.so: /usr/local/hplip/share/hplip/scan/plugins/bb_soap.so: wrong ELF class: ELFCLASS32
當然,這是示意訊息,原始錯誤訊息印象中是Segfault,但它的確標明了使用的library。
因為HP只將Protocol Close,掃描的上層是SANE,下層是HPMUD + libusb,示意圖如下:
所以透過修改程式,
可以在HPMUD和sane-hpaio backend加上printf,
就能知道它的呼叫flow,儘管它沒有Open,
也能知道傳遞什麼給事務機,步驟是什麼。
解析開始:
建立環境:
建個VM,USB map進去,按網樂通類似步驟把HPLIP、SANE、CUPS build出來。
找程式起始點:
首先先找hpaio backend的呼叫點,找到是在
hplip-3.14.10/scan/sane/
繼續找bb_soap的呼叫點,找到主要是
hplip-3.14.10/scan/sane/soap.c
再來找hpmud,找到是
hplip-3.14.10/io/hpmud/
主要應該是
hplip-3.14.10/io/hpmud/hpmud.c
至於hplip-3.14.10/io/mudext不用管它,看裡面有註明是給python用的library。
查看程式,修改程式碼,加printf:
看soap.c,看到
- ps->bb_open = get_library_symbol(ps->bb_handle, "bb_open")
- ps->bb_close = get_library_symbol(ps->bb_handle, "bb_close")
- ps->bb_get_parameters = get_library_symbol(ps->bb_handle, "bb_get_parameters")
- ps->bb_is_paper_in_adf = get_library_symbol(ps->bb_handle, "bb_is_paper_in_adf")
- ps->bb_start_scan = get_library_symbol(ps->bb_handle, "bb_start_scan")
- ps->bb_end_scan = get_library_symbol(ps->bb_handle, "bb_end_scan")
- ps->bb_get_image_data = get_library_symbol(ps->bb_handle, "bb_get_image_data")
- ps->bb_end_page = get_library_symbol(ps->bb_handle, "bb_end_page")
非常好,它將bb_soap的所有function都列好了,不用辛苦找。
接著在這些呼叫點前後加上printf,把原本的DBG改成printf。
hpmud裡面也是,把DBG都改成printf,看到open、close、read、write,都加上printf。
重新編譯後,執行
scanimage > AAA
看看AAA裡面有什麼,如下:
[10153] hpmud_probe_devices() bus=3 sane_hpaio_open(/usb/HP_Color_LaserJet_CM1015?serial=00CNF87DL012) io_mode = 1 [10153,13449,0,0,0,0] hpmud_device_open() uri=hp:/usb/HP_Color_LaserJet_CM1015?serial=00CNF87DL012 iomode=1 bb_open(session) [10153] hpmud_channel_open() dd=1 name=HP-SOAP-SCAN [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd380 size=154 sectime=45 [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd458 size=426 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd7b5c8 size=4096 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd7b5c8 size=4096 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd7b5c8 size=4096 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd7b5c8 size=4096 sectime=45 [10153] hpmud_channel_close() dd=1 cd=19 bb_open end sane_hpaio_control_option (option=mode action=auto value=na) sane_hpaio_control_option (option=resolution action=auto value=na) sane_hpaio_control_option (option=brightness action=auto value=na) sane_hpaio_control_option (option=contrast action=auto value=na) sane_hpaio_control_option (option=compression action=auto value=na) sane_hpaio_control_option (option=jpeg-quality action=auto value=na) sane_hpaio_control_option (option=tl-x action=auto value=na) sane_hpaio_control_option (option=tl-y action=auto value=na) sane_hpaio_control_option (option=br-x action=auto value=na) sane_hpaio_control_option (option=br-y action=auto value=na) sane_hpaio_get_option_descriptor(option=option-cnt) sane_hpaio_control_option (option=option-cnt action=get value=14) sane_hpaio_get_option_descriptor(option=option-cnt) sane_hpaio_control_option (option=option-cnt action=get value=14) sane_hpaio_get_option_descriptor(option=mode-group) sane_hpaio_get_option_descriptor(option=mode) sane_hpaio_get_option_descriptor(option=resolution) sane_hpaio_get_option_descriptor(option=advanced-group) sane_hpaio_get_option_descriptor(option=brightness) sane_hpaio_get_option_descriptor(option=contrast) sane_hpaio_get_option_descriptor(option=compression) sane_hpaio_get_option_descriptor(option=jpeg-quality) sane_hpaio_get_option_descriptor(option=geometry-group) sane_hpaio_get_option_descriptor(option=tl-x) sane_hpaio_get_option_descriptor(option=tl-y) sane_hpaio_get_option_descriptor(option=br-x) sane_hpaio_get_option_descriptor(option=br-y) sane_hpaio_control_option (option=br-x action=get value=14149222) sane_hpaio_control_option (option=tl-x action=get value=0) sane_hpaio_control_option (option=br-y action=get value=19459342) sane_hpaio_control_option (option=tl-y action=get value=0) sane_hpaio_control_option (option=tl-x action=get value=0) sane_hpaio_get_option_descriptor(option=br-x) sane_hpaio_control_option (option=br-x action=set value=14149222) sane_hpaio_control_option (option=tl-y action=get value=0) sane_hpaio_get_option_descriptor(option=br-y) sane_hpaio_control_option (option=br-y action=set value=19459342) sane_hpaio_start() bb_start_scan [10153] hpmud_channel_open() dd=1 name=HP-SOAP-SCAN [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd380 size=154 sectime=45 [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fffda5ca8f0 size=5 sectime=1 [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fffda5ca910 size=1359 sectime=1 [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd8a9 size=7 sectime=1 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 bb_start_scan end bb_get_parameters bb_get_parameters end set traits iPixelsPerRow=632 iBitsPerPixel=8 lNumRows=876 iComponentsPerPixel=1 cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=1024 output=(nil) outputAvail=0 outputThisPos=0 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=2048 output=(nil) outputAvail=0 outputThisPos=0 cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=3072 output=(nil) outputAvail=0 outputThisPos=0 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=4096 output=(nil) outputAvail=0 outputThisPos=0 cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=5120 output=(nil) outputAvail=0 outputThisPos=0 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=6144 output=(nil) outputAvail=0 outputThisPos=0 cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=7168 output=(nil) outputAvail=0 outputThisPos=0 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=8192 output=(nil) outputAvail=0 outputThisPos=0 cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=9216 output=(nil) outputAvail=0 outputThisPos=0 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 cnt=1024 index=0 input=0xd68e10 inputAvail=1024 inputUsed=1024 inputNextPos=10240 output=(nil) outputAvail=0 outputThisPos=0 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 cnt=450 index=0 input=0xd68e10 inputAvail=450 inputUsed=450 inputNextPos=10690 output=(nil) outputAvail=0 outputThisPos=0 cnt=0 index=0 input=(nil) inputAvail=0 inputUsed=0 inputNextPos=10690 output=(nil) outputAvail=0 outputThisPos=0 act traits iPixelsPerRow=637 iBitsPerPixel=1 lNumRows=876 iComponentsPerPixel=1 bb_getparameters bb_getparameters end sane_hpaio_get_parameters(): format=0, last_frame=1, lines=876, depth=1, pixels_per_line=637, bytes_per_line=80 P4 # SANE data follows 637 876 sane_hpaio_read() handle=0xd68720 data=0xd7ba40 maxLength=32768 cnt=0 index=0 input=(nil) inputAvail=0 inputUsed=0 inputNextPos=10690 output=0xd7ba40 outputAvail=32768 outputThisPos=0 -sane_hpaio_read() output=0xd7ba40 bytes_read=32768 maxLength=32768 status=0 ▒ ▒sane_hpaio_read() handle=0xd68720 data=0xd7ba40 maxLength=32768 cnt=0 index=0 input=(nil) inputAvail=0 inputUsed=0 inputNextPos=10690 output=0xd7ba40 outputAvail=32768 outputThisPos=32768 -sane_hpaio_read() output=0xd7ba40 bytes_read=32768 maxLength=32768 status=0 ▒ ▒sane_hpaio_read() handle=0xd68720 data=0xd7ba40 maxLength=32768 cnt=0 index=0 input=(nil) inputAvail=0 inputUsed=0 inputNextPos=10690 output=0xd7ba40 outputAvail=32768 outputThisPos=65536 -sane_hpaio_read() output=0xd7ba40 bytes_read=4544 maxLength=32768 status=0 sane_hpaio_read() handle=0xd68720 data=0xd7ba40 maxLength=32768 cnt=0 index=0 input=(nil) inputAvail=0 inputUsed=0 inputNextPos=10690 output=0xd7ba40 outputAvail=32768 outputThisPos=70080 bb_end_page [10153] hpmud_channel_close() dd=1 cd=19 bb_end_page end -sane_hpaio_read() output=0xd7ba40 bytes_read=0 maxLength=32768 status=5 sane_hpaio_cancel() bb_end_scan [10153] hpmud_channel_open() dd=1 name=HP-SOAP-SCAN [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd380 size=154 sectime=45 [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fffda5cb190 size=5 sectime=1 [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fffda5cb1b0 size=442 sectime=1 [10153] hpmud_channel_write() dd=1 cd=19 buf=0x7fca030fd8a9 size=7 sectime=1 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 [10153] hpmud_channel_read() dd=1 cd=19 buf=0xd83a68 size=4096 sectime=45 [10153] hpmud_channel_close() dd=1 cd=19 bb_end_scan end sane_hpaio_close() bb_close close end bb_unload bb unload end [10153] hpmud_device_close() dd=1
這整段一長串,會注意到:
1. bb_soap function呼叫流程,如下:
修改hpmud.c,在hpmud_channel_read和hpmud_channel_write裡面加上寫檔,
讀取和寫入的資料統統寫到檔案中,我是如下:
讀取部份:
hpmud_read_channel_1.dump
hpmud_read_channel_2.dump
.....
寫入部份:
hpmud_write_channel_1.dump
hpmud_write_channel_2.dump
.....
精彩的來了,我們看看它到底傳什麼給事務機,又從事務機收什麼回來?
cat /tmp/hpmud_write_channel_1.dump
cat /tmp/hpmud_write_channel_2.dump
cat /tmp/hpmud_read_channel_1.dump
cat /tmp/hpmud_read_channel_2.dump
dump出來的訊息好面熟,看起來很像是HTTP和XML啊.....
Google soap,查到:
SOAP Wiki
原來SOAP是以HTTP + XML為核心的物件描述語言,
而CM1015以SOAP做為溝通的通訊協定。
這裡有個部份我一開始想不通,它每份資料的斷點在哪裡?為何會出現19E這樣的神秘字串?
後來比對hpmud_read_channel和hpmud_write_channel的動作,搭配神秘數字0,
終於搞清楚它神秘字串是表示後面還有多少字要傳送或接收,
當這段資料後面沒東西時,就傳遞個0,表示後面沒資料,
有資料時,神秘字串是後一筆資料的字串長度的HEX表示。
以19E為例,19E表示:
本篇先到此為止,後續再戰。
- bb_open
- bb_start_scan
- bb_get_parameters
- bb_get_parameters
- bb_end_page
- bb_end_scan
- bb_close
- bb_unload
- hpmud_channel_open
- hpmud_channel_close
- hpmud_channel_read
- hpmud_channel_write
修改hpmud.c,在hpmud_channel_read和hpmud_channel_write裡面加上寫檔,
讀取和寫入的資料統統寫到檔案中,我是如下:
讀取部份:
hpmud_read_channel_1.dump
hpmud_read_channel_2.dump
.....
寫入部份:
hpmud_write_channel_1.dump
hpmud_write_channel_2.dump
.....
精彩的來了,我們看看它到底傳什麼給事務機,又從事務機收什麼回來?
cat /tmp/hpmud_write_channel_1.dump
POST / HTTP/1.1 Host: http:0 User-Agent: gSOAP/2.7 Content-Type: application/soap+xml; charset=utf-8 Transfer-Encoding: chunked Connection: close
cat /tmp/hpmud_write_channel_2.dump
19E <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wscn="http://tempuri.org/wscn.xsd"><SOAP-ENV:Body><wscn:GetScannerElements></wscn:GetScannerElements></SOAP-ENV:Body></SOAP-ENV:Envelope> 0
cat /tmp/hpmud_read_channel_1.dump
HTTP/1.1 200 OK Server: gSOAP/2.7 Content-Type: application/soap+xml; charset=utf-8 Transfer-Encoding: chunked Connection: close
cat /tmp/hpmud_read_channel_2.dump
7CB 1.1 200 OK Server: gSOAP/2.7 Content-Type: application/soap+xml; charset=utf-8 Transfer-Encoding: chunked Connection: close
dump出來的訊息好面熟,看起來很像是HTTP和XML啊.....
Google soap,查到:
SOAP Wiki
原來SOAP是以HTTP + XML為核心的物件描述語言,
而CM1015以SOAP做為溝通的通訊協定。
這裡有個部份我一開始想不通,它每份資料的斷點在哪裡?為何會出現19E這樣的神秘字串?
後來比對hpmud_read_channel和hpmud_write_channel的動作,搭配神秘數字0,
終於搞清楚它神秘字串是表示後面還有多少字要傳送或接收,
當這段資料後面沒東西時,就傳遞個0,表示後面沒資料,
有資料時,神秘字串是後一筆資料的字串長度的HEX表示。
以19E為例,19E表示:
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wscn="http://tempuri.org/wscn.xsd"><SOAP-ENV:Body><wscn:GetScannerElements></wscn:GetScannerElements></SOAP-ENV:Body></SOAP-ENV:Envelope>這整段的資料長度。
本篇先到此為止,後續再戰。
沒有留言:
張貼留言