破解SQLServer for Linux預覽版的3.5GB內存限制 (RHEL篇)

微軟發佈了SQLServer for Linux,可是安裝居然須要3.5GB內存,這讓大部分雲主機用戶都沒辦法嘗試這個新東西
這篇我將講解如何破解這個內存限制
要看關鍵的能夠直接跳到第6步,只須要替換4個字節就能夠破解這個限制python

  1. 首先按照微軟的給出的步驟安裝和配置
    https://docs.microsoft.com/zh-cn/sql/linux/sql-server-linux-setup-red-hatlinux

  2. 到執行/opt/mssql/bin/sqlservr-setup時能夠看到這個錯誤
sqlservr: This program requires a machine with at least 3250 megabytes of memory.
  1. 按錯誤文本查找消息在哪一個文件裏面
[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會檢測這個限制,而且這個限制是一個常量sql

  1. 查找錯誤消息的位置
[root@localhost bin]# hexdump -C sqlservr | less

找到這裏windows

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的位置less

  1. 查找調用錯誤消息的位置
[root@localhost bin]# objdump -C -S sqlservr | less

找到這裏dom

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,結果是隻有一處sqlserver

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..|
  1. 使用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中的限制值,可是不替換也可使用ui

  1. 繼續配置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裏面,若是須要破解其餘限制可能還須要花功夫研究這個文件
相關文章
相關標籤/搜索