-
Notifications
You must be signed in to change notification settings - Fork 28
AndBug 命令详解
分别是dev、pid、src 其中当当前只有一个dev设备时,不需要明确传入设备名。 没有源代码是可以不设置src参数 但是pid的参数是必须的
OPTIONS = ( ('pid', 'the process to be debugged, by pid or name'), ('dev', 'the device or emulator to be debugged (see adb)'), ('src', 'adds a directory where .java or .smali files could be found') )
两种启动方式: [启动方式一]: anbc@anbc-OptiPlex-780:~/workspace/andbug$ ./andbug shell -p 8224
AndBug (C) 2011 Scott W. Dunlop swdunlop@gmail.com
[启动方式二]: anbc@anbc-OptiPlex-780:~/workspace/andbug$ ./andbug shell -p com.example.test
AndBug (C) 2011 Scott W. Dunlop swdunlop@gmail.com
直接使用 classes命令,列举出指定应用的所有类信息 [0m>> classes 命令后跟一个字符串,列举出包含该字符串的类名的信息。 [0m>> classes Compound Loaded Classes [0m -- android.widget.CompoundButton$OnCheckedChangeListener [0m -- android.widget.CompoundButton
0x01 14命令输入输出数据 输入数据:无 输出数据:tag=1; tid=0xc240d71048L; jni=Lcom/google/android/mms/pdu/SendReq;; gen=; flags=7
列举出指定类名的所有方法信息。methods 后跟类名。 methods android.widget.CompoundButton methods com.example.test.MainActivity (Landroid/os/Bundle;)V methods com.example.test.MainActivity OnCreate(Landroid/os/Bundle;)V 这种命令方式有错误
调用细节:
call jdwp 0x01 14 获得应用中所有类的信息
call jdwp 0x02 0F 获得指定type id的方法信息
0x02 0F命令输入输出数据 输入数据:tid=0xc240ce7798L 输出输出:mid=0x43923008L name=onCreate jni=(Landroid/os/Bundle;)V gen= flags=0x4
break android.widget.CompoundButton Setting Hooks [0m -- Hooked android.widget.CompoundButton
调用细节: call jdwp 0x06 01 通过type id 和method id的值获得获得函数代码的起止位置等信息, 主要目的应该是在断点断掉后显示,停止位置的行号信息 call jdwp 0x0F 01 设置断点,
触发断点
call jdwp 0x0B 01 暂停当前线程 Breakpoint hit in thread <1> main, process suspended. call jdwp 0x01 08 暂停所有线程 call jdwp 0x0B 06 以thread id作为输入参数,返回当前线程的堆栈信息 -- com.example.test.MainActivity1ドル.onClick(Landroid/view/View;)V:0 call jdwp 0x02 0F 获得指定type id的获得方法信息 -- +++call load methods -- android.view.View.performClick()Z:18 call jdwp 0x02 0F -- +++call load methods -- android.view.View$PerformClick.run()V:2 call jdwp 0x02 0F -- +++call load methods -- android.os.Handler.handleCallback(Landroid/os/Message;)V:2 -- android.os.Handler.dispatchMessage(Landroid/os/Message;)V:4 call jdwp 0x02 0F -- +++call load methods -- android.os.Looper.loop()V:84 call jdwp 0x02 0F -- +++call load methods -- android.app.ActivityThread.main([Ljava/lang/String;)V:48 call jdwp 0x02 0F -- +++call load methods -- java.lang.reflect.Method.invokeNative(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Cla ss;[Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object; -- java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;: 17 call jdwp 0x02 0F -- +++call load methods -- com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run()V:11 call jdwp 0x02 0F -- +++call load methods -- com.android.internal.os.ZygoteInit.main([Ljava/lang/String;)V:66 call jdwp 0x02 0F -- +++call load methods -- dalvik.system.NativeStart.main([Ljava/lang/String;)V
[0m>> break android.widget.CompoundButton toggle Setting Hooks [0m -- Hooked android.widget.CompoundButton.toggle()V:0
0x0F 01 命令输入输出数据 作用:设置断点 输入数据: 40:EK_METHOD_ENTRY, 1: EVENT_THREAD, 1:modifiers(只有一个mod) 4:modKind是4,含义是 condition of type ClassRef (4) 针对4这个modkind值,需要传入一个指定的Reference TypeID buf.pack('11i1t', 40, 1, 1, 4, self.tid) #tid为type id EK_METHOD_ENTRY:在方法进入时设置断点 SP_THREAD:针对当前的线程 输出数据:eid=536870915 是一个request id的值
在设置方法断点时会触发0x06 x01命令 0x06 x01命令的输入输出数据 作用: 输入数据: type id refType The class. 类 ID信息 method id methodID The method. 方法ID信息 输出数据: Start Lowest valid code index for the method, >=0, or -1 if the method is native 函数行号起始位置 End Highest valid code index for the method, >=0, or -1 if the method is native 函数行号结束位置 Lines The number of entries in the line table for this method. 函数的行数 lineCodeIndex Initial code index of the line, start <= lineCodeIndex < end lineNumber Line number. 这块还不清楚
关于Location部分的输出信息, 其中的line数据标志其在源码中的行号 firstLoc=0 lastLoc=25 lineTable=5 loc=0 line=14 loc=3 line=15 loc=8 line=17 loc=16 line=19 loc=24 line=29
break com.example.test.MainActivity Setting Hooks call jdwp 0x06 01 firstLoc=0 lastLoc=4 lineTable=1 loc=0 line=10 call jdwp 0x0F 01 -- Hooked com.example.test.MainActivity.()V:0 break com.example.test.MainActivity test Setting Hooks call jdwp 0x06 01 firstLoc=0 lastLoc=11 lineTable=2 loc=0 line=33 loc=10 line=35 call jdwp 0x0F 01 -- Hooked com.example.test.MainActivity.test()V:0 break com.example.test.MainActivity onCreateOptionsMenu Setting Hooks call jdwp 0x06 01 firstLoc=0 lastLoc=11 lineTable=2 loc=0 line=42 loc=9 line=43 call jdwp 0x0F 01
设置方法断点时,一个过程,重点关注在Loction类中的方式
break com.example.test.MainActivity test Setting Hooks call jdwp 0x01 14 call jdwp 0x02 0F -- +++call load methods ()V (Landroid/os/Bundle;)V (Landroid/view/Menu;)Z ()V call jdwp 0x06 01 firstLoc=0 lastLoc=11 lineTable=2 in Loction class: tid=834310928568 mid=1133654136 loc=0 in Loction class: tid=834310928568 mid=1133654136 loc=11 loc=0 line=33 loc=10 line=35 in Loction class: tid=834310928568 mid=1133654136 loc=10 in Location.packTo: tag=1 tid=834310928568 mid=1133654136 loc=0 call jdwp 0x0F 01 eid=536870918 -- Hooked com.example.test.MainActivity.test()V:0
触发断点后的情况:
in Session.processEvent: ident=268435458 pol=1 ct=1 call jdwp 0x0B 01 Breakpoint hit in thread <1> main, process suspended. call jdwp 0x01 08 call jdwp 0x0B 06 in Loction class: tid=834311059480 mid=1133655696 loc=14 in Loction class: tid=834308458376 mid=1131158600 loc=18 in Loction class: tid=834310099384 mid=1132534272 loc=2 in Loction class: tid=834308833144 mid=1131613912 loc=2 in Loction class: tid=834308833144 mid=1131613976 loc=4 in Loction class: tid=834309758416 mid=1132312200 loc=84 in Loction class: tid=834308650984 mid=1131362400 loc=48 in Loction class: tid=834308305672 mid=1130761792 loc=-1 in Loction class: tid=834308305672 mid=1130762920 loc=17 in Loction class: tid=834310221480 mid=1133131960 loc=11 in Loction class: tid=834308629496 mid=1131319560 loc=66 in Loction class: tid=834308310160 mid=1130781664 loc=-1 -- com.example.test.MainActivity.test()V:0 call jdwp 0x02 0F -- +++call load methods -- com.example.test.MainActivity1ドル.onClick(Landroid/view/View;)V:14 call jdwp 0x02 0F -- +++call load methods -- android.view.View.performClick()Z:18 call jdwp 0x02 0F -- +++call load methods -- android.view.View$PerformClick.run()V:2 call jdwp 0x02 0F -- +++call load methods -- android.os.Handler.handleCallback(Landroid/os/Message;)V:2 -- android.os.Handler.dispatchMessage(Landroid/os/Message;)V:4 call jdwp 0x02 0F -- +++call load methods -- android.os.Looper.loop()V:84 call jdwp 0x02 0F -- +++call load methods -- android.app.ActivityThread.main([Ljava/lang/String;)V:48 call jdwp 0x02 0F -- +++call load methods -- java.lang.reflect.Method.invokeNative(Ljava/lang/Object;[Ljava/lang/Object ;Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object; -- java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljav a/lang/Object;:17 call jdwp 0x02 0F -- +++call load methods -- com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run()V:11 call jdwp 0x02 0F -- +++call load methods -- com.android.internal.os.ZygoteInit.main([Ljava/lang/String;)V:66 call jdwp 0x02 0F -- +++call load methods -- dalvik.system.NativeStart.main([Ljava/lang/String;)V
resume call jdwp 0x01 09 Process Resumed
0x0B 01命令:获取线程名称。似乎应该是 暂停线程命令 0x01 08命令: 暂停虚拟及命令 0x0B 06命令: 功能返回当前挂起线程的堆栈信息 0x02 0F命令:获取方法信息 0x01 09命令:恢复虚拟机的执行
[0m>> break-list Active Hooks [0m -- Hook <536870912> android.widget.CompoundButton <class 'andbug.vm.Class'> [0m -- Hook <536870913> android.widget.CompoundButton.toggle()V:0 <class 'andbug.vm.Location'>
和break命令有部分重合 与break的差别是,该命令不暂停线程,只对运行情况进行记录。 [0m>> class-trace android.widget.CompoundButton Setting Hooks [0m -- Hooked android.widget.CompoundButton [0m>>
call jdwp 0x0B 06 以thread id作为输入参数,返回当前线程的堆栈信息 call jdwp 0x02 0F 获得方法信息 -- +++call load methods -- com.example.test.MainActivity.test()V:0 call jdwp 0x06 05 获取一个方法中的参数和变量的信息 call jdwp 0x10 01 获得局部变量的值的信息 call jdwp 0x09 01 返回一个正在运行的对象的引用类型 call jdwp 0x02 0d 返回引用类型的JNI signature和generic signature -- this=Lcom/example/test/MainActivity; <830015946128> call jdwp 0x02 0F 获得指定方法的信息 -- +++call load methods -- com.example.test.MainActivity1ドル.onClick(Landroid/view/View;)V:14 call jdwp 0x06 05 call jdwp 0x10 01 call jdwp 0x09 01 call jdwp 0x02 0d -- this=Lcom/example/test/MainActivity1ドル; <830016101376> call jdwp 0x09 01 call jdwp 0x02 0d -- arg0=Landroid/widget/Button; <830016054232> call jdwp 0x02 0F -- +++call load methods -- android.view.View.performClick()Z:18 call jdwp 0x06 05 call jdwp 0x10 01 -- this=Landroid/widget/Button; <830016054232> call jdwp 0x09 01 call jdwp 0x02 0d -- li=Landroid/view/View$ListenerInfo; <830016101392> call jdwp 0x02 0F -- +++call load methods -- android.view.View$PerformClick.run()V:2 call jdwp 0x06 05 call jdwp 0x10 01 call jdwp 0x09 01 call jdwp 0x02 0d -- this=Landroid/view/View$PerformClick; <830016127040> call jdwp 0x02 0F -- +++call load methods -- android.os.Handler.handleCallback(Landroid/os/Message;)V:2 call jdwp 0x06 05 call jdwp 0x10 01 call jdwp 0x09 01 call jdwp 0x02 0d -- message=Landroid/os/Message; <830016133224> -- android.os.Handler.dispatchMessage(Landroid/os/Message;)V:4 call jdwp 0x06 05 call jdwp 0x10 01 call jdwp 0x09 01 call jdwp 0x02 0d -- this=Landroid/view/ViewRootImpl$ViewRootHandler; <830016104112> -- msg=Landroid/os/Message; <830016133224> call jdwp 0x02 0F -- +++call load methods -- android.os.Looper.loop()V:84 call jdwp 0x06 05 call jdwp 0x10 01 call jdwp 0x09 01 call jdwp 0x02 0d -- me=Landroid/os/Looper; <830015919016> -- msg=Landroid/os/Message; <830016133224> -- ident=43147241456493 -- logging=None call jdwp 0x09 01 call jdwp 0x02 0d -- queue=Landroid/os/MessageQueue; <830015919048> call jdwp 0x02 0F -- +++call load methods -- android.app.ActivityThread.main([Ljava/lang/String;)V:48 call jdwp 0x06 05 call jdwp 0x10 01 call jdwp 0x0d 01 -- args=[] call jdwp 0x09 01 call jdwp 0x02 0d -- thread=Landroid/app/ActivityThread; <830015919160> call jdwp 0x02 0F -- +++call load methods -- java.lang.reflect.Method.invokeNative(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Cla ss;[Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;
java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;:
17
call jdwp 0x06 05 call jdwp 0x10 01 call jdwp 0x09 01 call jdwp 0x02 0d -- this=Ljava/lang/reflect/Method; <830015916184> call jdwp 0x0d 01 call jdwp 0x0d 02 call jdwp 0x0d 01 call jdwp 0x09 01 call jdwp 0x02 0d -- args=([],) -- receiver=None call jdwp 0x02 0F -- +++call load methods -- com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run()V:11 call jdwp 0x06 05 call jdwp 0x10 01 call jdwp 0x09 01 call jdwp 0x02 0d -- this=Lcom/android/internal/os/ZygoteInit$MethodAndArgsCaller; <830015916576> call jdwp 0x02 0F -- +++call load methods -- com.android.internal.os.ZygoteInit.main([Ljava/lang/String;)V:66 call jdwp 0x06 05 call jdwp 0x10 01 -- caller=Lcom/android/internal/os/ZygoteInit$MethodAndArgsCaller; <830015916576> call jdwp 0x0d 01 call jdwp 0x0d 02 call jdwp 0x0A 01 返回一个字符串中包含的字符内容 call jdwp 0x0A 01 -- argv=(#'com.android.internal.os.ZygoteInit', #'start-system-server') call jdwp 0x02 0F 通过一个引用类型返回其包含的方法的通用签名信息 -- +++call load methods -- dalvik.system.NativeStart.main([Ljava/lang/String;)V call jdwp 0x0B 03 命令是0x0b 0x03 重新启动线程
和break命令有一部分重复
method-trace android.widget.CompoundButton.toggle Setting Hooks [0m -- Hooked android.widget.CompoundButton.toggle()V:0 [0m>>
全参数调用命令方式:
method-trace com.example.test.MainActivity.test(Ljava/lang/String;IJLcom/example/test/MainActivity;)V cpath=Lcom/example/test/MainActivity; mname=test mjni=(Ljava/lang/String;IJLcom/example/test/MainActivity;)V
eid=536870917 in Hook init ident=536870917 -- Hooked com.example.test.MainActivity.test(Ljava/lang/String;IJLcom/example/test/MainActivity;)V:0
dump android.widget.CompoundButton toggle !! could not find source for android.widget.CompoundButton 这里的dump出来的不是java源代码,而是通过apktool等工具获得的java汇编代码。
无任何参数
参数可以跟具体的命令名称 ./andbug help
./andbug shell -p 234
./andbug shell -p android.process.acore
-p 参数后可以跟进程id,也可以跟包名
参数:保存源代码的路径。支持相对路径,和相对用户文件夹的路径 源码目录到这个层级 /home/anbc/workspace/test/src
如:应用packeage=com.test.android 代码放在目录/home/anbc/workspace/test/src/com.test.android中 设置源代码的方式是: source /home/anbc/workspace/test/src
inspect 参数为object对象。 如: inspect 830013343248
inspect 830013343248 In inspect.find_object k=this v=Landroid/os/MessageQueue; <830015918704> In inspect.find_object k=nextPollTimeoutMillis v=-1 In inspect.find_object k=pendingIdleHandlerCount v=0 In inspect.find_object k=me v=Landroid/os/Looper; <830015918672> In inspect.find_object k=queue v=Landroid/os/MessageQueue; <830015918704> In inspect.find_object k=ident v=43147241461362 In inspect.find_object k=args v=[] In inspect.find_object k=thread v=Landroid/app/ActivityThread; <830015918816> In inspect.find_object k=this v=Ljava/lang/reflect/Method; <830015916320> In inspect.find_object k=args v=([],) In inspect.find_object k=receiver v=None In inspect.find_object k=this v=Lcom/android/internal/os/ZygoteInit$MethodAndArgsCaller; <830015916472> In inspect.find_object k=caller v=Lcom/android/internal/os/ZygoteInit$MethodAndArgsCaller; <830015916472> buf=<jdwp.JdwpBuffer object at 0x92f3750> None None call jdwp 0x0A 01 buf=<jdwp.JdwpBuffer object at 0x92f38b8> None None In inspect.find_object k=argv v=(#'com.android.internal.os.ZygoteInit', #'start-system-server') In inspect.find_object k=this v=Ljava/lang/Daemons$FinalizerWatchdogDaemon; <830013424992> In inspect.find_object k=this v=Ljava/lang/Daemons$FinalizerWatchdogDaemon; call jdwp 0x06 05 In inspect.find_object k=this v=Ljava/lang/Daemons$FinalizerWatchdogDaemon; <830013424992> In inspect.find_object k=this v=Ljava/lang/Thread; <830015912072> In inspect.find_object k=this v=Ljava/lang/ref/ReferenceQueue; <830013343248>
In inspect obj.oid=830013343248 jni=Ljava/lang/ref/ReferenceQueue; thread=thread <7> FinalizerDaemon In inspect k=head v=None type=NoneType -- head=None
threads thread <1> main [0m thread <2> GC [0m thread <3> Signal Catcher [0m thread <5> Compiler [0m thread <6> ReferenceQueueDaemon [0m thread <7> FinalizerDaemon [0m thread <8> FinalizerWatchdogDaemon [0m thread <9> Binder_1 [0m thread <10> Binder_2 [0m thread <11> Binder_3 [0m thread <12> CookieSyncManager [0m thread <13> pool-2-thread-1 [0m thread <15> BackgroundHandler [0m>>
第二种使用方法: threads verbose=2
Verbose的取值可能是1、2、3 verbose=1显示当前虚拟的的线程信息;显示每个线程当前中断点的堆栈信息 verbose=2 增加当前中断点中,各变量的名称类型的信息 andbug.screed.item("%s=<%s>" % (k, type(v).name)) verbose>2 增加变量值的显示 以上andbug.screed.item("%s=%s <%s>" % (k, v, type(v).name)) 没有verbose参数,只显示线程信息
需要bottle库。应该是一个web展示的页面 需要安装bottle库,来实现。
参数为指定类的路径 statics com.android.internal.view.menu.MenuBuilder
处理详情: 第一次完整的命令: Static Fields, com.android.internal.view.menu.MenuBuilder call jdwp 0x02 0E Load Field 输入的type id call jdwp 0x02 06 返回一个引用类型中的一个或多个静态变量的值,返回静态变量的值,输入是type id call jdwp 0x0A 01 获取一个字符串的内容
-- PRESENTER_KEY = android:menu:presenters call jdwp 0x0A 01 -- TAG = MenuBuilder call jdwp 0x0d 01 返回数组的长度 call jdwp 0x0d 02 获得指定数组元素的值 -- sCategoryToOrder = (1, 4, 5, 3, 2, 0) call jdwp 0x0A 01 -- ACTION_VIEW_STATES_KEY = android:menu:actionviewstates call jdwp 0x0A 01 -- EXPANDED_ACTION_VIEW_ID = android:menu:expandedactionview
第二次完整的命令: AndBug (C) 2011 Scott W. Dunlop swdunlop@gmail.com
statics com.tencent.tmsecure.common.j call jdwp 0x01 14 Static Fields, com.tencent.tmsecure.common.j statics tid(type_id)= 834311004864 load_fields tid=834311004864 call jdwp 0x02 0E field_id=Field:145941612 name=bJI jni=Z gen= flags=74 field_id=Field:145941644 name=bJJ jni=Z gen= flags=74 field_id=Field:145941676 name=bJK jni=Landroid/content/BroadcastReceiver; gen= flags=10 the fields len = 3 static field id=1087349600 static field id=1087349624 static field id=1087349648 call jdwp 0x02 06 获取指定类型中的静态变量信息 call jdwp 0x09 01 call jdwp 0x02 0d
-- bJK = Lcom/tencent/tmsecure/common/j1ドル; <830016038000> -- bJJ = False -- bJI = True
0x02 0E命令输入输出数据
输入数据:load_fields tid=834311004864 输入数据为指定的type id的值
输出数据:
field_id=Field:145941612 name=bJI jni=Z gen= flags=74
field_id=Field:145941644 name=bJJ jni=Z gen= flags=74
field_id=Field:145941676 name=bJK jni=Landroid/content/BroadcastReceiver; gen= flags=10
作用:获取指定类中的几个静态变量的信息
0x01 14 命令输入输出的数据 输入数据: statics tid(type_id)= 834311004864 [The reference type ID. 对应类的type id] the fields len = 3 [The number of values to get. 要获取静态变量的个数] static field id=1087349600 [A field to get 要获取的field的id值] static field id=1087349624 static field id=1087349648 输出数据:各静态变量的值 bJK = Lcom/tencent/tmsecure/common/j1ドル; <830016038000> -- bJJ = False -- bJI = True 作用:获取特定对象的变量的值的信息
0x0A 01 命令的输入输出数据 作用:获取一个指定字符串的值 输入数据:The String object ID. 字符串对象ID 输出数据:UTF-8 representation of the string value. 用utf-8格式表示的字符串的值
0x0d01 命令的输入输出数据 作用:获取指定对象中,元素的个数 输入数据:The array object ID. 数组对象ID值 输出数据:The length of the array. 数组的长度值
0x0d 02命令的输入输出数据 作用:获取一个数组中连续的几个元素的值 输入数据:The array object ID. 数组对象的ID The first index to retrieve. 用于检索的起始偏移量 The number of components to retrieve. 所要检索的元素的个数 输出数据:The retrieved values. If the values are objects, they are tagged-values; otherwise, they are untagged-values 检索获取的值,如果值是对象,它为标签值;否则为非标签值
如果跟一个具体的线程名称作为参数,暂停指定的线程,如果没有参数,则暂停整个应用
suspend main Suspending Threads -- suspended thread <1> main
如果跟一个具体的线程名称作为参数,则回复指定线程的运行,如果没有参数,则恢复整个应用的运行
resume main Resuming Threads -- resumed thread <1> main
目前涉及的JDWP命令:
Line 146: code, buf = conn.request(0x1001, buf.data())
Line 176: code, buf = conn.request(0x0B01, buf.data())
Line 189: code, buf = conn.request(0x0B03, buf.data())
Line 212: code, buf = conn.request(0x0B06, buf.data())
Line 236: code, buf = conn.request(0x0B07, buf.data())
Line 252: code, buf = conn.request(0x0B01, buf.data())
Line 295: code, buf = conn.request(0x0F01, buf.data())
Line 383: code, buf = conn.request(0x0601, data)
Line 433: code, buf = conn.request(0x0605, data)
Line 484: code, buf = conn.request(0x020D, buf.data())
Line 505: code, buf = conn.request(0x020E, buf.data())
Line 543: code, buf = conn.request(0x0206, buf.data())
Line 568: code, buf = conn.request(0x020F, buf.data())
Line 646: code, buf = conn.request(0x0F01, buf.data())
Line 763: code, buf = self.conn.request(0x0114)
Line 801: code, buf = self.conn.request(0x0108, '')
Line 813: code, buf = self.conn.request(0x0108, '')
Line 824: code, buf = self.conn.request(0x0109, '')
Line 838: code, buf = conn.request(0x010A, '')
Line 850: code, buf = self.conn.request(0x0104, '')
Line 912: code, buf = conn.request(0x0901, buf.data())
Line 945: code, buf = conn.request(0x0902, buf.data())
Line 1000: code, buf = conn.request(0x0d01, buf.data())
Line 1036: code, buf = conn.request(0x0d02, buf.data())
Line 1069: code, buf = conn.request(0x0A01, buf.data())