当前位置: 首页 > 工具软件 > super-bbs > 使用案例 >

android superuser.apk 管理root权限原理分析

简培
2023-12-01

使用android 手机很多情况下需要root权限,关于root权限获取的原理可以参考以下文章:
1、云中漫步博客:  Android系统root破解原理分析     http://my.unix-center.net/~Simon_fu/?p=1069
2、云中漫步 ? Android系统root破解原理分析(续) http://my.unix-center.net/~Simon_fu/?p=1100
3、zergRush - 随想专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/tomken_zhang/article/details/6866260
4、zergRush (补充) - 随想专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/tomken_zhang/article/details/6870104
5、结合init源码剖析android root提权漏洞(CVE-2010-E... http://bbs.pediy.com/showthread.php?t=139738
6、Android提权代码zergRush分析 | i, Claud http://blog.claudxiao.net/2011/10/zergrush
.........

原理是利用了android的两个提权漏洞: CVE-2010-EASY 和 ZergRush。 我把大概原理简单说说:
1, CVE-2010-EASY : linux的内核的模块化程度很高,很多功能模块是需要到时候再加载,在 android中由init进程来管理这些的。但是这个init进程不会检测发给它的指令的来源,不管是内核发送的,还是用户发送的,它都执行不误,会顺从的去加载或卸载一些模块,而加载的模块都是以root身份运行的。因此你可以给它准备一个精心制作的功能模块(ko文件),然后触发相应的加载条件,比如热拔插、开关wifi等等, 该功能模块运行后,会生成 /data/local/tmp/rootshell    一个带s位的shell。
2,ZergRush原理: 具有root权限的vold进程使用了libsysutils.so库,该库有个函数存在栈溢出,因此可以root权限执行输入的shellcode。

印象中好像还有个提权漏洞,原理大概是: 某root权限的进程在干完一些事情后会自动降权到普通权限,但是如果普通权限的进程数满了,它就降权不成功,接着它就堂而皇之的以root权限运行了,好像是adbd进程。

扯了半天还没扯到superuser.apk,这个程序是root成功后,专门用来管理root权限使用的,防止被恶意程序滥用。我一直很好奇他是怎么做到这一点的,         

源码地址:
http://superuser.googlecode.com/svn/trunk
这个源码有点老,不过感觉原理和最新的superuser应该是差不多的。
带着两个问题我们来分析源码:
1、superuser是怎么知道谁想用root权限?  
2、superuser是如何把用户的选择告诉su程序的那? 
即superuser和su程序是如何通讯的,他们俩位于不通的时空,一个在java虚拟机中,一个在linux的真实进程中。

共有两个active: SuperuserActivity 和 SuperuserRequestActivity ,呵呵比较简单。
其中SuperuserActivity 主要是用来管理白名单的,就是记住哪个程序已经被允许使用root权限了,省的每次用时都问用户。
SuperuserRequestActivity 就是用来询问用户目前有个程序想使用root权限,是否允许,是否一直允许,即放入白名单。

这个白名单比较关键,是一个sqlite数据库文件,位置:
/data/data/com.koushikdutta.superuser/databases/superuser.sqlite

看完一开始我列的文章,就能明白root的本质就是往 /system/bin/ 下放一个带s位的,不检查调用者权限的su文件。普通程序可以调用该su来运行root权限的命令。superuser.apk中就自带了一个这样的su程序。一开始superuser会检测/system/bin/su是否存在,是否是老子自个放进去的su:

<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="pln" style="color: rgb(0, 0, 0);">             </span><span class="typ" style="color: rgb(102, 0, 102);">File</span><span class="pln" style="color: rgb(0, 0, 0);"> su </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">new</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(102, 0, 102);">File</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="str" style="color: rgb(0, 136, 0);">"/system/bin/su"</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">             </span><span class="com" style="color: rgb(136, 0, 0);">// 检测su文件是否存在,如果不存在则直接返回</span>
<span class="pln" style="color: rgb(0, 0, 0);">             </span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">(!</span><span class="pln" style="color: rgb(0, 0, 0);">su</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">exists</span><span class="pun" style="color: rgb(102, 102, 0);">())</span><span class="pln" style="color: rgb(0, 0, 0);">        </span>
<span class="pln" style="color: rgb(0, 0, 0);">             </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln" style="color: rgb(0, 0, 0);">                 </span><span class="typ" style="color: rgb(102, 0, 102);">Toast</span><span class="pln" style="color: rgb(0, 0, 0);"> toast </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(102, 0, 102);">Toast</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">makeText</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="kwd" style="color: rgb(0, 0, 136);">this</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="str" style="color: rgb(0, 136, 0);">"Unable to find /system/bin/su."</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(102, 0, 102);">Toast</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">LENGTH_LONG</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">                 toast</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">show</span><span class="pun" style="color: rgb(102, 102, 0);">();</span>
<span class="pln" style="color: rgb(0, 0, 0);">                 </span><span class="kwd" style="color: rgb(0, 0, 136);">return</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln" style="color: rgb(0, 0, 0);">             </span><span class="pun" style="color: rgb(102, 102, 0);">}</span></p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="com" style="color: rgb(136, 0, 0);">//检测su文件的完整性,比较大小,太省事了吧</span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="com" style="color: rgb(136, 0, 0);">//如果大小一样,则认为su文件正确,直接返回了事。</span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">su</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">length</span><span class="pun" style="color: rgb(102, 102, 0);">()</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">==</span><span class="pln" style="color: rgb(0, 0, 0);"> suStream</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">available</span><span class="pun" style="color: rgb(102, 102, 0);">())</span><span class="pln" style="color: rgb(0, 0, 0);">  </span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln" style="color: rgb(0, 0, 0);">    suStream</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">close</span><span class="pun" style="color: rgb(102, 102, 0);">();</span><span class="pln" style="color: rgb(0, 0, 0);"> </span>
<span class="pln" style="color: rgb(0, 0, 0);">    </span><span class="kwd" style="color: rgb(0, 0, 136);">return</span><span class="pun" style="color: rgb(102, 102, 0);">;</span><span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="com" style="color: rgb(136, 0, 0);">//</span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="pun" style="color: rgb(102, 102, 0);">}</span>
</p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="pln" style="color: rgb(0, 0, 0);">            </span>
</p>

<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="pln" style="color: rgb(0, 0, 0);">  </span><span class="com" style="color: rgb(136, 0, 0);">// 如果检测到/system/bin/su 文件存在,但是不对头,则把自带的su先写到"/data/data/com.koushikdutta.superuser/su"</span>
<span class="pln" style="color: rgb(0, 0, 0);">    </span><span class="com" style="color: rgb(136, 0, 0);">//      再写到/system/bin/su。</span></p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;">
</p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="pln" style="color: rgb(0, 0, 0);">                        </span><span class="kwd" style="color: rgb(0, 0, 136);">byte</span><span class="pun" style="color: rgb(102, 102, 0);">[]</span><span class="pln" style="color: rgb(0, 0, 0);"> bytes </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">new</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">byte</span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="pln" style="color: rgb(0, 0, 0);">suStream</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">available</span><span class="pun" style="color: rgb(102, 102, 0);">()];</span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="typ" style="color: rgb(102, 0, 102);">DataInputStream</span><span class="pln" style="color: rgb(0, 0, 0);"> dis </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">new</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(102, 0, 102);">DataInputStream</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">suStream</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   dis</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">readFully</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">bytes</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="typ" style="color: rgb(102, 0, 102);">FileOutputStream</span><span class="pln" style="color: rgb(0, 0, 0);"> suOutStream </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">new</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(102, 0, 102);">FileOutputStream</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="str" style="color: rgb(0, 136, 0);">"/data/data/com.koushikdutta.superuser/su"</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   suOutStream</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">write</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">bytes</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   suOutStream</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">close</span><span class="pun" style="color: rgb(102, 102, 0);">();</span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="typ" style="color: rgb(102, 0, 102);">Process</span><span class="pln" style="color: rgb(0, 0, 0);"> process </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(102, 0, 102);">Runtime</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">getRuntime</span><span class="pun" style="color: rgb(102, 102, 0);">().</span><span class="kwd" style="color: rgb(0, 0, 136);">exec</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="str" style="color: rgb(0, 136, 0);">"su"</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="typ" style="color: rgb(102, 0, 102);">DataOutputStream</span><span class="pln" style="color: rgb(0, 0, 0);"> os </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">new</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="typ" style="color: rgb(102, 0, 102);">DataOutputStream</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">process</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">getOutputStream</span><span class="pun" style="color: rgb(102, 102, 0);">());</span>
<span class="pln" style="color: rgb(0, 0, 0);">   os</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">writeBytes</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="str" style="color: rgb(0, 136, 0);">"mount -oremount,rw /dev/block/mtdblock3 /system\n"</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   os</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">writeBytes</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="str" style="color: rgb(0, 136, 0);">"busybox cp /data/data/com.koushikdutta.superuser/su /system/bin/su\n"</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   os</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">writeBytes</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="str" style="color: rgb(0, 136, 0);">"busybox chown 0:0 /system/bin/su\n"</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   os</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">writeBytes</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="str" style="color: rgb(0, 136, 0);">"chmod 4755 /system/bin/su\n"</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   os</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">writeBytes</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="str" style="color: rgb(0, 136, 0);">"exit\n"</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   os</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">flush</span><span class="pun" style="color: rgb(102, 102, 0);">();</span>
</p>

上面提到的su肯定是动过手脚的, 我 最纳闷的就是有进程使用root权限,superuser是怎么知道的,看完su 的代码明白了,关键是句:
<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="pln" style="color: rgb(0, 0, 0);">  sprintf</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">sysCmd</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="str" style="color: rgb(0, 136, 0);">"am start -a <a target=_blank href="http://lib.csdn.net/base/android" class="replace_word" title="Android知识库" target="_blank" style="color: rgb(223, 52, 52); text-decoration: none; font-weight: bold;">Android</a>.intent.action.MAIN </span>
</p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="str" style="color: rgb(0, 136, 0);">                                 -n com.koushikdutta.superuser/com.koushikdutta.superuser.SuperuserRequestActivity </span>
</p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="str" style="color: rgb(0, 136, 0);">                                 --ei uid %d --ei pid %d > /dev/null"</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> g_puid</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> ppid</span><span class="pun" style="color: rgb(102, 102, 0);">);</span></p><p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="pln" style="color: rgb(0, 0, 0);">  </span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">system</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">sysCmd</span><span class="pun" style="color: rgb(102, 102, 0);">))</span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="kwd" style="color: rgb(0, 0, 136);">return</span><span class="pln" style="color: rgb(0, 0, 0);"> executionFailure</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="str" style="color: rgb(0, 136, 0);">"am."</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
</p>
原理是am命令,看了下am的用法,明白了:

  usage: am [subcommand] [options]

    start an Activity: am start [-D] [-W] <INTENT>
        -D: enable debugging
        -W: wait for launch to complete

    start a Service: am startservice <INTENT>

    send a broadcast Intent: am broadcast <INTENT>

    start an Instrumentation: am instrument [flags] <COMPONENT>
        -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)
        -e <NAME> <VALUE>: set argument <NAME> to <VALUE>
        -p <FILE>: write profiling data to <FILE>
        -w: wait for instrumentation to finish before returning

    start profiling: am profile <PROCESS> start <FILE>
    stop profiling: am profile <PROCESS> stop

    <INTENT> specifications include these flags:
        [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
        [-c <CATEGORY> [-c <CATEGORY>] ...]
        [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
        [--esn <EXTRA_KEY> ...]
        [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
        [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
        [-n <COMPONENT>] [-f <FLAGS>]
        [--grant-read-uri-permission] [--grant-write-uri-permission]
        [--debug-log-resolution]
        [--activity-brought-to-front] [--activity-clear-top]
        [--activity-clear-when-task-reset] [--activity-exclude-from-recents]
        [--activity-launched-from-history] [--activity-multiple-task]
        [--activity-no-animation] [--activity-no-history]
        [--activity-no-user-action] [--activity-previous-is-top]
        [--activity-reorder-to-front] [--activity-reset-task-if-needed]
        [--activity-single-top]
        [--receiver-registered-only] [--receiver-replace-pending]
        [<URI>]


还有个疑点,就是su怎么知道用户是允许root权限还是反对那? 原来是上面提到的白名单起来作用,superuser把用户的选择放入  :
/data/data/com.koushikdutta.superuser/databases/superuser.sqlite    数据库中,然后su进程再去读该数据库来判断是否允许。

<p style="margin-top: 0px; margin-bottom: 10px; padding-top: 0px; padding-bottom: 0px;"><span class="kwd" style="color: rgb(0, 0, 136);">static</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">int</span><span class="pln" style="color: rgb(0, 0, 0);"> checkWhitelist</span><span class="pun" style="color: rgb(102, 102, 0);">()</span>
<span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln" style="color: rgb(0, 0, 0);"> sqlite3 </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="pln" style="color: rgb(0, 0, 0);">db</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">int</span><span class="pln" style="color: rgb(0, 0, 0);"> rc </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> sqlite3_open_v2</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">DBPATH</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">&</span><span class="pln" style="color: rgb(0, 0, 0);">db</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> SQLITE_OPEN_READWRITE</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> NULL</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">(!</span><span class="pln" style="color: rgb(0, 0, 0);">rc</span><span class="pun" style="color: rgb(102, 102, 0);">)</span>
<span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln" style="color: rgb(0, 0, 0);">  </span><span class="kwd" style="color: rgb(0, 0, 136);">char</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">*</span><span class="pln" style="color: rgb(0, 0, 0);">errorMessage</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln" style="color: rgb(0, 0, 0);">  </span><span class="kwd" style="color: rgb(0, 0, 136);">char</span><span class="pln" style="color: rgb(0, 0, 0);"> query</span><span class="pun" style="color: rgb(102, 102, 0);">[</span><span class="lit" style="color: rgb(0, 102, 102);">1024</span><span class="pun" style="color: rgb(102, 102, 0);">];</span>
<span class="pln" style="color: rgb(0, 0, 0);">  sprintf</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">query</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="str" style="color: rgb(0, 136, 0);">"select * from whitelist where _id=%d limit 1;"</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> g_puid</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">  </span><span class="kwd" style="color: rgb(0, 0, 136);">struct</span><span class="pln" style="color: rgb(0, 0, 0);"> whitelistCallInfo callInfo</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln" style="color: rgb(0, 0, 0);">  callInfo</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">count </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="lit" style="color: rgb(0, 102, 102);">0</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln" style="color: rgb(0, 0, 0);">  callInfo</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">db </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> db</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln" style="color: rgb(0, 0, 0);">  rc </span><span class="pun" style="color: rgb(102, 102, 0);">=</span><span class="pln" style="color: rgb(0, 0, 0);"> sqlite3_exec</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">db</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> query</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> whitelistCallback</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">&</span><span class="pln" style="color: rgb(0, 0, 0);">callInfo</span><span class="pun" style="color: rgb(102, 102, 0);">,</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">&</span><span class="pln" style="color: rgb(0, 0, 0);">errorMessage</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">  </span><span class="kwd" style="color: rgb(0, 0, 136);">if</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">rc </span><span class="pun" style="color: rgb(102, 102, 0);">!=</span><span class="pln" style="color: rgb(0, 0, 0);"> SQLITE_OK</span><span class="pun" style="color: rgb(102, 102, 0);">)</span>
<span class="pln" style="color: rgb(0, 0, 0);">  </span><span class="pun" style="color: rgb(102, 102, 0);">{</span>
<span class="pln" style="color: rgb(0, 0, 0);">   sqlite3_close</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">db</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">   </span><span class="kwd" style="color: rgb(0, 0, 136);">return</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="lit" style="color: rgb(0, 102, 102);">0</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln" style="color: rgb(0, 0, 0);">  </span><span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="pln" style="color: rgb(0, 0, 0);">  sqlite3_close</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">db</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);">  </span><span class="kwd" style="color: rgb(0, 0, 136);">return</span><span class="pln" style="color: rgb(0, 0, 0);"> callInfo</span><span class="pun" style="color: rgb(102, 102, 0);">.</span><span class="pln" style="color: rgb(0, 0, 0);">count</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="pun" style="color: rgb(102, 102, 0);">}</span>
<span class="pln" style="color: rgb(0, 0, 0);"> sqlite3_close</span><span class="pun" style="color: rgb(102, 102, 0);">(</span><span class="pln" style="color: rgb(0, 0, 0);">db</span><span class="pun" style="color: rgb(102, 102, 0);">);</span>
<span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="kwd" style="color: rgb(0, 0, 136);">return</span><span class="pln" style="color: rgb(0, 0, 0);"> </span><span class="lit" style="color: rgb(0, 102, 102);">0</span><span class="pun" style="color: rgb(102, 102, 0);">;</span>
<span class="pun" style="color: rgb(102, 102, 0);">}</span>
</p>

至此分析结束,回头看看,原来如此,又想起初中老师的一句话:会者不难,难者不会。    其实原理都不难,只要用心。
 类似资料: