ITPub博客

首页 > 数据库 > > 厉害了 word哥! 破解SQL for Linux ctp1的3.5GB内存限制 (RHEL篇)

厉害了 word哥! 破解SQL for Linux ctp1的3.5GB内存限制 (RHEL篇)

作者:浪花小雨滴 时间:2020-05-14 16:10:12 0 删除 编辑

微软发布了SQLServer for Linux,但是安装竟然需要3.5GB内存,这让大部分云主机用户都没办法尝试这个新东西
这篇我将讲解如何破解这个内存限制
要看关键的可以直接跳到第6步,只需要替换4个字节就可以破解这个限制

  1. 首先按照微软的给出的步骤安装和配置
    https://docs.microsoft.com/zh-cn/sql/linux/sql-server-linux-setup-red-hat

  2. 到执行/opt/mssql/bin/sqlservr-setup时可以看到这个错误

    sqlservr: This program requires a machine with at least 3250 megabytes of memory.
  3. 按错误文本查找消息在哪个文件里面

    [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会检测这个限制,并且这个限制是一个常量

  4. 查找错误消息的位置

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

  5. 查找调用错误消息的位置

    [root@localhost bin]# objdump -C -S sqlservr | less

    找到这里

       23940:       48 8d 35 af 81 04 00    lea    0x481af(%%rip),%%rsi        # 6baf6
       23947:       31 c                   xor    %%eax,%%eax   23949:       48 89 ca                mov    %%rcx,%%rdx   2394c:       48 89 d9                mov    %%rbx,%%rcx   2394f:       e8 6c e4 fe ff          callq  11dc <fprintf@plt>   23954:       bf 01 00 00 00          mov    $0x1,%%edi   23959:       e8 e2 e1 fe ff          callq  11b4 <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    $0xc1b7108,%%esi   1486f:       4c 89 e7                mov    %%r12,%%rdi   14872:       e8 69 f 00 00          callq  238e

    顺道再用hexdump查找一下有多少处地方用了80 10 b7 c1,结果是只有一处

    0001486  00 00 48 89 df e8 66 15  00 00 be 80 10 b7 c1 4c  |..H...f........L|0001487  89 e7 e8 69 f 00 00 f  57 c f 29 85 70 ff ff  |...i....W..).p..|
  6. 使用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中的限制值,但是不替换也可以使用

  7. 继续配置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/sqlservrDec 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里面,如果需要破解其他限制可能还需要花功夫研究这个文件


文章转载自:http://www.cnblogs.com/zkweb/p/6136826.html


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3158255/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-05-16

  • 博文量
    4259
  • 访问量
    39962