微軟發佈了SQLServer for Linux,但是安裝竟然需要3.5GB記憶體,這讓大部分雲主機用戶都沒辦法嘗試這個新東西 這篇我將講解如何破解這個記憶體限制 要看關鍵的可以直接跳到第6步,只需要替換4個位元組就可以破解這個限制 1. 首先按照微軟的給出的步驟安裝和配置 https://docs.mi ...
微軟發佈了SQLServer for Linux,但是安裝竟然需要3.5GB記憶體,這讓大部分雲主機用戶都沒辦法嘗試這個新東西
這篇我將講解如何破解這個記憶體限制
要看關鍵的可以直接跳到第6步,只需要替換4個位元組就可以破解這個限制
首先按照微軟的給出的步驟安裝和配置
https://docs.microsoft.com/zh-cn/sql/linux/sql-server-linux-setup-red-hat到執行/opt/mssql/bin/sqlservr-setup時可以看到這個錯誤
sqlservr: This program requires a machine with at least 3250 megabytes of memory.
按錯誤文本查找消息在哪個文件裡面
[root@localhost ~]# cd /opt/mssql/bin/ [root@localhost bin]# grep -irn "3250" [root@localhost bin]# grep -irn "megabytes of memory" Binary file sqlpackage matches Binary file sqlpackage matches Binary file sqlservr matches [root@localhost bin]# strings sqlservr | grep "megabytes of memory" %s: This program requires a machine with at least %zu megabytes of memory. [root@localhost bin]# strings sqlpackage | grep "megabytes of memory" %s: This program requires a machine with at least %zu megabytes of memory.
看來sqlservr和sqlpackage會檢測這個限制,並且這個限制是一個常量
查找錯誤消息的位置
[root@localhost bin]# hexdump -C sqlservr | less
找到這裡
0006baf0 72 69 6e 67 29 00 25 73 3a 20 54 68 69 73 20 70 |ring).%s: This p| 0006bb00 72 6f 67 72 61 6d 20 72 65 71 75 69 72 65 73 20 |rogram requires |
可以看到消息在0006baf6的位置
查找調用錯誤消息的位置
[root@localhost bin]# objdump -C -S sqlservr | less
找到這裡
23940: 48 8d 35 af 81 04 00 lea 0x481af(%rip),%rsi # 6baf6 23947: 31 c0 xor %eax,%eax 23949: 48 89 ca mov %rcx,%rdx 2394c: 48 89 d9 mov %rbx,%rcx 2394f: e8 6c e4 fe ff callq 11dc0 <fprintf@plt> 23954: bf 01 00 00 00 mov $0x1,%edi 23959: e8 e2 e1 fe ff callq 11b40 <exit@plt>
判斷的函數在這裡
238e0: 55 push %rbp 238e1: 48 89 e5 mov %rsp,%rbp 238e4: 53 push %rbx 238e5: 48 83 ec 78 sub $0x78,%rsp // 把這個函數接收的第二個參數放到rbx // 參考 https://en.wikipedia.org/wiki/X86_calling_conventions (System V AMD64 ABI) 238e9: 48 89 f3 mov %rsi,%rbx // 調用sysinfo獲取記憶體大小 // rdi是第一個參數,是一個在堆棧中的struct sysinfo // 參考 https://linux.die.net/man/2/sysinfo 238ec: 48 8d 7d 88 lea -0x78(%rbp),%rdi 238f0: e8 3b e3 fe ff callq 11c30 <sysinfo@plt> // 偏移量的計算如下 // -0x78: uptime (struct sysinfo的開頭地址) // -0x70: loads[3] // -0x58: totalram // -0x50: freeram // -0x48: sharedram // -0x40: bufferram // -0x38: totalswap // -0x30: freeswap // -0x28: procs (short為什麼占8個位元組?看https://en.wikipedia.org/wiki/Data_structure_alignment) // -0x20: totalhigh // -0x18: freehigh // -0x10: mem_unit (同樣,int 4個位元組 align 4個位元組) // 計算出rax = totalram * mem_unit 238f5: 8b 45 f0 mov -0x10(%rbp),%eax 238f8: 48 0f af 45 a8 imul -0x58(%rbp),%rax // 如果rax小於rbx則跳到23909,即顯示記憶體不足並退出 238fd: 48 39 d8 cmp %rbx,%rax 23900: 72 07 jb 23909 23902: 48 83 c4 78 add $0x78,%rsp 23906: 5b pop %rbx 23907: 5d pop %rbp 23908: c3 retq
調用判斷的函數的代碼在這裡
// 這裡的第二個參數是3250000000,可以看到記憶體的限制值是一個常量 // 0xc1b71080 = 3250000000 1486a: be 80 10 b7 c1 mov $0xc1b71080,%esi 1486f: 4c 89 e7 mov %r12,%rdi 14872: e8 69 f0 00 00 callq 238e0
順道再用hexdump查找一下有多少處地方用了80 10 b7 c1,結果是只有一處
00014860 00 00 48 89 df e8 66 15 00 00 be 80 10 b7 c1 4c |..H...f........L| 00014870 89 e7 e8 69 f0 00 00 0f 57 c0 0f 29 85 70 ff ff |...i....W..).p..|
使用python修改代碼
改條件判斷的jb或者改8010b7c1都可以,我這裡把8010b7c1改成更小的值0080841e(512M)[root@localhost bin]# mv sqlservr sqlservr.old [root@localhost bin]# python >>> a = open("sqlservr.old", "rb").read() >>> b = a.replace("\x80\x10\xb7\xc1", "\x00\x80\x84\x1e") >>> open("sqlservr", "wb").write(b) [root@localhost bin]# chmod +x sqlservr
可以繼續替換掉sqlpackage中的限制值,但是不替換也可以使用
繼續配置sqlserver
[root@localhost bin]# /opt/mssql/bin/sqlservr-setup [root@localhost bin]# systemctl status mssql-server
如果你執行完命令後沒有看到服務正常啟動,可能是之前的配置沒有成功導致的
刪除mssql的數據文件夾並重試即可[root@localhost bin]# rm -rf /var/opt/mssql [root@localhost bin]# /opt/mssql/bin/sqlservr-setup
正常啟動後可以看到
● mssql-server.service - Microsoft(R) SQL Server(R) Database Engine
Loaded: loaded (/usr/lib/systemd/system/mssql-server.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2016-12-05 22:50:06 EST; 20s ago
Main PID: 2625 (sqlservr)
CGroup: /system.slice/mssql-server.service
├─2625 /opt/mssql/bin/sqlservr
└─2638 /opt/mssql/bin/sqlservr
Dec 05 22:50:10 localhost.localdomain sqlservr[2625]: 2016-12-06 03:50:10.85 spid17s Server is listening on [ 0.0.0.0 ...433].
Dec 05 22:50:10 localhost.localdomain sqlservr[2625]: 2016-12-06 03:50:10.87 Server Server is listening on [ 127.0.0....434].
Dec 05 22:50:10 localhost.localdomain sqlservr[2625]: 2016-12-06 03:50:10.89 Server Dedicated admin connection suppor...1434.
Dec 05 22:50:10 localhost.localdomain sqlservr[2625]: 2016-12-06 03:50:10.89 spid17s SQL Server is now ready for clien...ired.
Dec 05 22:50:11 localhost.localdomain sqlservr[2625]: 2016-12-06 03:50:11.77 spid6s Starting up database 'tempdb'.
Dec 05 22:50:12 localhost.localdomain sqlservr[2625]: 2016-12-06 03:50:12.02 spid6s The tempdb database has 1 data file(s).
Dec 05 22:50:12 localhost.localdomain sqlservr[2625]: 2016-12-06 03:50:12.02 spid20s The Service Broker endpoint is in...tate.
Dec 05 22:50:12 localhost.localdomain sqlservr[2625]: 2016-12-06 03:50:12.03 spid20s The Database Mirroring endpoint i...tate.
Dec 05 22:50:12 localhost.localdomain sqlservr[2625]: 2016-12-06 03:50:12.09 spid20s Service Broker manager has started.
Dec 05 22:50:12 localhost.localdomain sqlservr[2625]: 2016-12-06 03:50:12.14 spid5s Recovery is complete. This is an ...ired.
Hint: Some lines were ellipsized, use -l to show in full.
啟動成功後使用微軟提供的命令行工具連接也可以,使用windows上的客戶端連接也可以
https://docs.microsoft.com/zh-cn/sql/linux/sql-server-linux-setup-tools
下圖是2G記憶體上運行的mssql
Ubuntu上的破解會不一樣,因為Ubuntu安裝前會運行檢測程式,如何破解將在下一篇講解
題外話
- mssql for linux有日期限制和聯網驗證,預計正式版以後免費的可能性很小
- mssql在linux上編譯開啟了pie選項並且沒有符號表導出,這讓gdb跟蹤變得很困難,但這次破解只需要靜態分析
- mssql的本體封在了/opt/mssql/lib/sqlservr.sfp裡面,如果需要破解其他限制可能還需要花功夫研究這個文件