lamda 7.90__tar.gz → 8.5__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. {lamda-7.90 → lamda-8.5}/PKG-INFO +1 -1
  2. lamda-8.5/README.md +46 -0
  3. {lamda-7.90 → lamda-8.5}/lamda/__init__.py +1 -1
  4. {lamda-7.90 → lamda-8.5}/lamda/client.py +72 -61
  5. {lamda-7.90 → lamda-8.5}/lamda/exceptions.py +2 -0
  6. {lamda-7.90 → lamda-8.5}/lamda/rpc/application.proto +4 -0
  7. {lamda-7.90 → lamda-8.5}/lamda/rpc/services.proto +3 -3
  8. {lamda-7.90 → lamda-8.5}/lamda.egg-info/PKG-INFO +1 -1
  9. lamda-7.90/README.md +0 -43
  10. {lamda-7.90 → lamda-8.5}/lamda/bcast.proto +0 -0
  11. {lamda-7.90 → lamda-8.5}/lamda/const.py +0 -0
  12. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/any.proto +0 -0
  13. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/api.proto +0 -0
  14. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/compiler/plugin.proto +0 -0
  15. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/descriptor.proto +0 -0
  16. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/duration.proto +0 -0
  17. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/empty.proto +0 -0
  18. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/field_mask.proto +0 -0
  19. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/source_context.proto +0 -0
  20. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/struct.proto +0 -0
  21. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/timestamp.proto +0 -0
  22. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/type.proto +0 -0
  23. {lamda-7.90 → lamda-8.5}/lamda/google/protobuf/wrappers.proto +0 -0
  24. {lamda-7.90 → lamda-8.5}/lamda/rpc/debug.proto +0 -0
  25. {lamda-7.90 → lamda-8.5}/lamda/rpc/file.proto +0 -0
  26. {lamda-7.90 → lamda-8.5}/lamda/rpc/policy.proto +0 -0
  27. {lamda-7.90 → lamda-8.5}/lamda/rpc/proxy.proto +0 -0
  28. {lamda-7.90 → lamda-8.5}/lamda/rpc/settings.proto +0 -0
  29. {lamda-7.90 → lamda-8.5}/lamda/rpc/shell.proto +0 -0
  30. {lamda-7.90 → lamda-8.5}/lamda/rpc/status.proto +0 -0
  31. {lamda-7.90 → lamda-8.5}/lamda/rpc/storage.proto +0 -0
  32. {lamda-7.90 → lamda-8.5}/lamda/rpc/types.proto +0 -0
  33. {lamda-7.90 → lamda-8.5}/lamda/rpc/uiautomator.proto +0 -0
  34. {lamda-7.90 → lamda-8.5}/lamda/rpc/util.proto +0 -0
  35. {lamda-7.90 → lamda-8.5}/lamda/rpc/wifi.proto +0 -0
  36. {lamda-7.90 → lamda-8.5}/lamda/types.py +0 -0
  37. {lamda-7.90 → lamda-8.5}/lamda.egg-info/SOURCES.txt +0 -0
  38. {lamda-7.90 → lamda-8.5}/lamda.egg-info/dependency_links.txt +0 -0
  39. {lamda-7.90 → lamda-8.5}/lamda.egg-info/not-zip-safe +0 -0
  40. {lamda-7.90 → lamda-8.5}/lamda.egg-info/requires.txt +0 -0
  41. {lamda-7.90 → lamda-8.5}/lamda.egg-info/top_level.txt +0 -0
  42. {lamda-7.90 → lamda-8.5}/setup.cfg +0 -0
  43. {lamda-7.90 → lamda-8.5}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamda
3
- Version: 7.90
3
+ Version: 8.5
4
4
  Summary: Android reverse engineering & automation framework (Client API)
5
5
  Home-page: https://github.com/firerpa/lamda
6
6
  Author: rev1si0n
lamda-8.5/README.md ADDED
@@ -0,0 +1,46 @@
1
+ <p align="center">
2
+ <img src="image/logo.svg" alt="FIRERPA" width="345">
3
+ </p>
4
+
5
+ <p align="center">安卓 RPA 机器人框架,下一代移动端数据自动化机器人</p>
6
+
7
+ <p align="center">
8
+ <img src="https://img.shields.io/badge/python-3.6+-blue.svg?logo=python&labelColor=yellow" />
9
+ <img src="https://img.shields.io/badge/android-6.0--15-blue.svg?logo=android&labelColor=white" />
10
+ <img src="https://img.shields.io/badge/root%20require-red.svg?logo=android&labelColor=black" />
11
+ <img src="https://img.shields.io/github/downloads/rev1si0n/lamda/total" />
12
+ <img src="https://img.shields.io/github/v/release/rev1si0n/lamda" />
13
+ </p>
14
+
15
+ <p align="center"><a href="https://device-farm.com/doc/index.html">使用文档</a> | <a href="https://t.me/lamda_dev">TELEGRAM</a> | <a href="https://qm.qq.com/q/zDaX2a594I">QQ 群组</a> | <a href="https://device-farm.com/doc/版本历史.html">更新历史</a></p>
16
+
17
+ 智能机崛起,传统网页端的普及度也开始显著减弱,数据与应用正加速向移动端转移。越来越多的人选择通过智能手机和平板等移动设备来获取信息和服务。随着移动设备的普及,用户享受到更便捷访问体验,传统的网页内容模式面临重新审视。与此同时,数据采集的技术也亟需适应这一趋势。过去,许多数据采集工具专注于网页内容,在移动端环境中,尤其是在移动端封闭的黑盒中,现今的常规技术也面临着新的挑战,FIRERPA 创造了可能,将这一切变得更加简单快捷。
18
+
19
+ FIRERPA 是**安卓领域的集大成者**,设计为减少**安全分析**及**应用测试**或**自动化**工作的时间和琐碎问题,经过超 500 台设备集群的生产环境考验,稳定应用于多个大型系统,包括自动化取证,云平台,数据采集,合规分析等,完全商业级软件的质量和稳定性,仅需 root 权限即可正常运行。具备 **ARM/X86** 全架构,安卓 **6.0-15** 的广泛兼容性([16 KB page size](https://developer.android.com/guide/practices/page-sizes) 的安卓 15 适配中),支持 **模拟器**、**真机**、**云手机**、 **WSA**(Windows Subsystem for Android™️)、**RK开发板** (所有 ARM 架构)以及 **Redroid** 等大多数运行安卓系统的设备。为**移动端 RPA 和数据自动化**提供稳定的解决方案,以**编程化**的**接口**替代大量手动操作,**易部署**,没有那些复杂花哨不跨平台的安装流程,你所需要的能力他大概率能做到并且做的更好。他并不是一个单一功能的框架,他是集 Appium、uiautomator **自动化**的超集同时具备**逆向**领域如 **Hook** **抓包** **证书安装** **组网** **API跟踪** **手机自控** 等等各种能力的框架。当然,FIRERPA 可以做到的远不止于此,你可以阅读使用文档尽情探索他的所有能力。
20
+
21
+
22
+ <h3><p align="center">适用广泛的服务架构设计</p></h3>
23
+
24
+ <p align="center">FIRERPA 不同于任何其他同类或者子集软件,在设计之初即考虑到了各种可能的应用环境,可在非侵入的情况下运行在当下绝大部分的安卓设备内,即插即用,没有任何外部依赖,无需任何多余设置,原生即是为大型的业务场景设计,易于系统化的管理及更新。而此时,其他具备相似功能的软件还在经历掉线、不稳定、兼容性差、无人维护、管理难度大等各种问题。</p>
25
+
26
+ <h3><p align="center">丰富编程接口为业务赋能</p></h3>
27
+
28
+ <p align="center">提供多达 160 条编程 API 接口,让你可以对安卓设备进行无微不至的管理和操作,提供了包括命令执行,系统设置,系统状态,应用相关,自动化控制,代理以及文件等十几个大类的接口。同时提供了封装完整的 Python 库让你可以快速上手使用。规范及稳定的服务和接口让你可以无忧的通过代码控制每一个细节,甚至可以让其和 AI 进行互联,让大模型自动编写以及执行任务。</p>
29
+
30
+ <h3><p align="center">简洁易用的远程桌面</p></h3>
31
+
32
+ <p align="center">
33
+ <img src="image/demo.gif" alt="动图演示" width="95%">
34
+ </p>
35
+
36
+ <h3><p align="center">一键中间人流量分析及更多其他功能</p></h3>
37
+
38
+ 支持常规以及国际APP流量分析,DNS流量分析,得益于 [mitmproxy flow hook](https://docs.mitmproxy.org/stable/api/events.html),你可以对任何请求做到最大限度的掌控,mitmproxy 功能足够丰富,你可以使用 Python 脚本实时修改或者捕获应用的请求,也可以通过其 `Export` 选项导出特定请求的 `curl` 命令或者 `HTTPie` 命令,分析重放、拦截修改、功能组合足以替代你用过的任何此类商业/非商业软件。如果你仍不清楚 mitmproxy 是什么以及其具有的能力,请务必先查找相关文档,因为 FIRERPA 将会使用 mitmproxy 为你展现应用请求。
39
+
40
+ <p align="center">
41
+ <img src="image/mitm.gif" alt="动图演示" width="95%">
42
+ </p>
43
+
44
+ <p align="center">
45
+ 当然,FIRERPA 提供的能力不止于这些,他是你强有力的设备控制及管理工具,感兴趣请转到 使用文档。
46
+ </p>
@@ -2,4 +2,4 @@
2
2
  #
3
3
  # Distributed under MIT license.
4
4
  # See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5
- __version__ = "7.90"
5
+ __version__ = "8.5"
@@ -88,6 +88,7 @@ __all__ = [
88
88
  "Orientation",
89
89
  "OpenVPNProfile",
90
90
  "GproxyProfile",
91
+ "TouchBuilder",
91
92
  "Selector",
92
93
  "TouchWait",
93
94
  "TouchMove",
@@ -256,6 +257,7 @@ TouchSequence.load = classmethod(touchSequenceLoad)
256
257
  TouchSequence.save = touchSequenceSave
257
258
  TouchSequence.appendAction = touchSequenceAppendAction
258
259
  TouchSequence.appendDown = touchSequenceAppendDown
260
+ TouchSequence.appendMove = touchSequenceAppendMove
259
261
  TouchSequence.appendWait = touchSequenceAppendWait
260
262
  TouchSequence.appendUp = touchSequenceAppendUp
261
263
 
@@ -302,9 +304,6 @@ class CustomOcrBackend(object):
302
304
 
303
305
 
304
306
  class BaseCryptor(object):
305
- def __str__(self):
306
- return "{}".format(self.__class__.__name__)
307
- __repr__ = __str__
308
307
  def encrypt(self, data):
309
308
  return data
310
309
  def decrypt(self, data):
@@ -312,9 +311,6 @@ class BaseCryptor(object):
312
311
 
313
312
 
314
313
  class BaseServiceStub(object):
315
- def __str__(self):
316
- return "{}".format(self.__class__.__name__)
317
- __repr__ = __str__
318
314
  def __init__(self, stub):
319
315
  self.stub = stub
320
316
 
@@ -334,6 +330,29 @@ class FernetCryptor(BaseCryptor):
334
330
  return key
335
331
 
336
332
 
333
+ class TouchBuilder(object):
334
+ def __init__(self):
335
+ self.s = TouchSequence()
336
+ def down(self, x, y, pressure=50, track=0):
337
+ self.s.appendDown(tid=track, x=x, y=y,
338
+ pressure=pressure)
339
+ return self
340
+ def move(self, x, y, pressure=50, track=0):
341
+ self.s.appendMove(tid=track, x=x, y=y,
342
+ pressure=pressure)
343
+ return self
344
+ def up(self, track=0):
345
+ self.s.appendUp(tid=track)
346
+ return self
347
+ def wait(self, mills):
348
+ self.s.appendWait(wait=mills)
349
+ return self
350
+ def build(self):
351
+ sequence = TouchSequence()
352
+ sequence.CopyFrom(self.s)
353
+ return sequence
354
+
355
+
337
356
  class ClientLoggingInterceptor(ClientInterceptor):
338
357
  def truncate_string(self, s):
339
358
  return "{:.1024}...".format(s) if len(s) > 1024 else s
@@ -467,8 +486,6 @@ class ObjectUiAutomatorOpStub:
467
486
  corner=corner)
468
487
  r = self.stub.selectorClickExists(req)
469
488
  return r.value
470
- def click_exist(self, *args, **kwargs):
471
- return self.click_exists(*args, **kwargs)
472
489
  def long_click(self, corner=Corner.COR_CENTER):
473
490
  """
474
491
  长按选择器选中的控件
@@ -484,26 +501,12 @@ class ObjectUiAutomatorOpStub:
484
501
  req = protos.SelectorOnlyRequest(selector=self.selector)
485
502
  r = self.stub.selectorExists(req)
486
503
  return r.value
487
- def exist(self, *args, **kwargs):
488
- return self.exists(*args, **kwargs)
489
504
  def info(self):
490
505
  """
491
506
  获取选择器选中控件的信息
492
507
  """
493
508
  req = protos.SelectorOnlyRequest(selector=self.selector)
494
509
  return self.stub.selectorObjInfo(req)
495
- def info_of_all_instances(self):
496
- """
497
- 获取选择器选中的所有控件的信息
498
- """
499
- req = protos.SelectorOnlyRequest(selector=self.selector)
500
- r = self.stub.selectorObjInfoOfAllInstances(req)
501
- return r.objects
502
- def all_instances(self):
503
- """
504
- 获取选择器选中的所有元素控件
505
- """
506
- return list(self)
507
510
  def _new_object(self, **kwargs):
508
511
  selector = copy.deepcopy(self._selector)
509
512
  selector.update(**kwargs)
@@ -559,6 +562,11 @@ class ObjectUiAutomatorOpStub:
559
562
  return self._new_object(index=idx)
560
563
  def instance(self, idx):
561
564
  return self._new_object(instance=idx)
565
+ def get(self, idx):
566
+ """
567
+ 获取匹配的第 N 个索引的元素
568
+ """
569
+ return self.instance(idx)
562
570
  def __iter__(self):
563
571
  """
564
572
  遍历所有符合选择器条件的元素实例
@@ -1042,16 +1050,21 @@ class AppScriptRpcInterface(object):
1042
1050
  self.application = application
1043
1051
  self.stub = stub
1044
1052
  self.name = name
1053
+ def __str__(self):
1054
+ return "{}:Script:{}".format(self.application,
1055
+ self.name)
1056
+ __repr__ = __str__
1045
1057
  def __call__(self, *args):
1046
1058
  call_args = dict()
1047
1059
  call_args["method"] = self.name
1048
1060
  call_args["args"] = args
1049
1061
  req = HookRpcRequest()
1050
1062
  req.package = self.application.applicationId
1063
+ req.user = self.application.user
1051
1064
  req.callinfo = json.dumps(call_args)
1052
1065
  result = self.stub.callScript(req)
1053
- r = json.loads(result.callresult)
1054
- return r
1066
+ data = json.loads(result.callresult)
1067
+ return data
1055
1068
 
1056
1069
 
1057
1070
  class ApplicationOpStub:
@@ -1063,8 +1076,8 @@ class ApplicationOpStub:
1063
1076
  self.applicationId = applicationId
1064
1077
  self.stub = stub
1065
1078
  def __str__(self):
1066
- return "{}:{}".format(self.stub.__class__.__name__,
1067
- self.applicationId)
1079
+ return "Application:{}@{}".format(self.applicationId,
1080
+ self.user)
1068
1081
  __repr__ = __str__
1069
1082
  def is_foreground(self):
1070
1083
  """
@@ -1118,7 +1131,7 @@ class ApplicationOpStub:
1118
1131
  req.user = self.user
1119
1132
  r = self.stub.isPermissionGranted(req)
1120
1133
  return r.value
1121
- def delete_cache(self):
1134
+ def clear_cache(self):
1122
1135
  """
1123
1136
  清空应用的缓存数据(非数据仅缓存)
1124
1137
  """
@@ -1126,7 +1139,7 @@ class ApplicationOpStub:
1126
1139
  req.user = self.user
1127
1140
  r = self.stub.deleteApplicationCache(req)
1128
1141
  return r.value
1129
- def reset_data(self):
1142
+ def reset(self):
1130
1143
  """
1131
1144
  清空应用的所有数据
1132
1145
  """
@@ -1134,8 +1147,6 @@ class ApplicationOpStub:
1134
1147
  req.user = self.user
1135
1148
  r = self.stub.resetApplicationData(req)
1136
1149
  return r.value
1137
- def reset(self):
1138
- return self.reset_data()
1139
1150
  def start(self):
1140
1151
  """
1141
1152
  启动应用
@@ -1226,27 +1237,34 @@ class ApplicationOpStub:
1226
1237
  req.spawn = spawn
1227
1238
  req.destination = emit
1228
1239
  req.encode = encode
1240
+ req.user = self.user
1229
1241
  r = self.stub.attachScript(req)
1230
1242
  return r.value
1231
1243
  def detach_script(self):
1232
1244
  """
1233
1245
  移除注入应用的 Hook 脚本
1234
1246
  """
1235
- req = protos.String(value=self.applicationId)
1247
+ req = protos.HookRequest()
1248
+ req.package = self.applicationId
1249
+ req.user = self.user
1236
1250
  r = self.stub.detachScript(req)
1237
1251
  return r.value
1238
1252
  def is_attached_script(self):
1239
1253
  """
1240
1254
  检查使用在此应用注入了 Hook 脚本
1241
1255
  """
1242
- req = protos.String(value=self.applicationId)
1256
+ req = protos.HookRequest()
1257
+ req.package = self.applicationId
1258
+ req.user = self.user
1243
1259
  r = self.stub.isScriptAttached(req)
1244
1260
  return r.value
1245
1261
  def is_script_alive(self):
1246
1262
  """
1247
1263
  检查应用中的 Hook 脚本是否正常
1248
1264
  """
1249
- req = protos.String(value=self.applicationId)
1265
+ req = protos.HookRequest()
1266
+ req.package = self.applicationId
1267
+ req.user = self.user
1250
1268
  r = self.stub.isScriptAlive(req)
1251
1269
  return r.value
1252
1270
  def __getattr__(self, name):
@@ -1263,7 +1281,7 @@ class ApplicationStub(BaseServiceStub):
1263
1281
  获取当前处于前台的应用的信息
1264
1282
  """
1265
1283
  top = self.stub.currentApplication(protos.Empty())
1266
- app = self.__call__(top.packageName)
1284
+ app = self.__call__(top.packageName, user=top.user)
1267
1285
  app.activity = top.activity
1268
1286
  return app
1269
1287
  def get_application_by_name(self, name, user=0):
@@ -1305,6 +1323,7 @@ class ApplicationStub(BaseServiceStub):
1305
1323
  安装设备上的 apk 文件(注意此路径为设备上的 apk 路径)
1306
1324
  """
1307
1325
  req = protos.ApplicationRequest(path=fpath)
1326
+ req.user = self.user
1308
1327
  r = self.stub.installFromLocalFile(req)
1309
1328
  return r
1310
1329
  def __call__(self, applicationId, user=0):
@@ -1312,10 +1331,6 @@ class ApplicationStub(BaseServiceStub):
1312
1331
 
1313
1332
 
1314
1333
  class StorageOpStub:
1315
- def __str__(self):
1316
- return "{}:{}".format(self.stub.__class__.__name__,
1317
- self.name)
1318
- __repr__ = __str__
1319
1334
  # 用于容器值序列化的方法
1320
1335
  def _decrypt(self, data):
1321
1336
  return self.cryptor.decrypt(data)
@@ -1734,20 +1749,20 @@ class ProxyStub(BaseServiceStub):
1734
1749
 
1735
1750
 
1736
1751
  class SelinuxPolicyStub(BaseServiceStub):
1737
- def policy_set_allow(self, source, target, tclass, action):
1752
+ def allow(self, source, target, tclass, action):
1738
1753
  """
1739
1754
  selinux allow
1740
1755
  """
1741
1756
  req = protos.SelinuxPolicyRequest(source=source, target=target,
1742
- tclass=tclass, action=action)
1757
+ tclass=tclass, action=action)
1743
1758
  r = self.stub.policySetAllow(req)
1744
1759
  return r.value
1745
- def policy_set_disallow(self, source, target, tclass, action):
1760
+ def disallow(self, source, target, tclass, action):
1746
1761
  """
1747
1762
  selinux disallow
1748
1763
  """
1749
1764
  req = protos.SelinuxPolicyRequest(source=source, target=target,
1750
- tclass=tclass, action=action)
1765
+ tclass=tclass, action=action)
1751
1766
  r = self.stub.policySetDisallow(req)
1752
1767
  return r.value
1753
1768
  def get_enforce(self):
@@ -1763,27 +1778,27 @@ class SelinuxPolicyStub(BaseServiceStub):
1763
1778
  req = protos.Boolean(value=enforced)
1764
1779
  r = self.stub.setEnforce(req)
1765
1780
  return r.value
1766
- def is_enabled(self):
1781
+ def enabled(self):
1767
1782
  """
1768
1783
  获取设备上的 selinux 是否已经启用
1769
1784
  """
1770
1785
  r = self.stub.isEnabled(protos.Empty())
1771
1786
  return r.value
1772
- def policy_set_enforce(self, name):
1787
+ def enforce(self, name):
1773
1788
  """
1774
1789
  设置一个域为 enforce
1775
1790
  """
1776
1791
  req = protos.String(value=name)
1777
1792
  r = self.stub.policySetEnforce(req)
1778
1793
  return r.value
1779
- def policy_set_permissive(self, name):
1794
+ def permissive(self, name):
1780
1795
  """
1781
1796
  设置一个域为 permissive
1782
1797
  """
1783
1798
  req = protos.String(value=name)
1784
1799
  r = self.stub.policySetPermissive(req)
1785
1800
  return r.value
1786
- def policy_create_domain(self, name):
1801
+ def create_domain(self, name):
1787
1802
  """
1788
1803
  新建一个 selinux 域
1789
1804
  """
@@ -2022,11 +2037,6 @@ class OcrOperator(object):
2022
2037
  OCR - 检查元素是否存在
2023
2038
  """
2024
2039
  return bool(self.find_target_item())
2025
- def exist(self):
2026
- """
2027
- OCR - 检查元素是否存在
2028
- """
2029
- return self.exists()
2030
2040
  def click(self):
2031
2041
  """
2032
2042
  OCR - 点击元素(不存在则报错)
@@ -2037,11 +2047,6 @@ class OcrOperator(object):
2037
2047
  OCR - 点击元素(不存在将不会产生异常)
2038
2048
  """
2039
2049
  return self.find_cb(self._click, False)
2040
- def click_exist(self):
2041
- """
2042
- OCR - 点击元素(不存在将不会产生异常)
2043
- """
2044
- return self.click_exists()
2045
2050
  def screenshot(self, quality=100):
2046
2051
  """
2047
2052
  OCR - 对元素进行截图
@@ -2123,6 +2128,15 @@ class Device(object):
2123
2128
  policy["maxBackoff"] = "15s"
2124
2129
  config = json.dumps(dict(methodConfig=[{"name": [{}],
2125
2130
  "retryPolicy": policy,}]))
2131
+ option = dict()
2132
+ option["grpc.max_send_message_length"] = 64*1024*1024
2133
+ option["grpc.max_receive_message_length"] = 128*1024*1024
2134
+ option["grpc.keepalive_time_ms"] = 30*1000
2135
+ option["grpc.keepalive_timeout_ms"] = 15*1000
2136
+ option["grpc.keepalive_permit_without_calls"] = True
2137
+ option["grpc.max_pings_without_data"] = 0
2138
+ option["grpc.service_config"] = config
2139
+ option["grpc.enable_http_proxy"] = 0
2126
2140
  if certificate is not None:
2127
2141
  with open(certificate, "rb") as fd:
2128
2142
  key, crt, ca = self._parse_certdata(fd.read())
@@ -2132,13 +2146,10 @@ class Device(object):
2132
2146
  self._chan = grpc.secure_channel(self.server, creds,
2133
2147
  options=(("grpc.ssl_target_name_override",
2134
2148
  self._parse_cname(crt)),
2135
- ("grpc.service_config", config),
2136
- ("grpc.enable_http_proxy",
2137
- 0)))
2149
+ *tuple(option.items()),))
2138
2150
  else:
2139
2151
  self._chan = grpc.insecure_channel(self.server,
2140
- options=(("grpc.service_config", config),
2141
- ("grpc.enable_http_proxy", 0))
2152
+ options=(*tuple(option.items()),)
2142
2153
  )
2143
2154
  session = session or uuid.uuid4().hex
2144
2155
  interceptors = [ClientSessionMetadataInterceptor(session),
@@ -22,6 +22,8 @@ class InvalidAndroidPackage(Exception):
22
22
  """ Exception """
23
23
  class InvalidArgumentError(Exception):
24
24
  """ Exception """
25
+ class InvalidOperationError(Exception):
26
+ """ Exception """
25
27
  class InvalidRootCertificate(Exception):
26
28
  """ Exception """
27
29
  class MethodNotFoundException(Exception):
@@ -54,6 +54,7 @@ message ApplicationActivityInfo {
54
54
  int64 flags = 7;
55
55
  bool debug = 8;
56
56
  string data = 9;
57
+ uint32 user = 10;
57
58
  }
58
59
 
59
60
  message ApplicationActivityInfoList {
@@ -77,6 +78,7 @@ message ApplicationInfo {
77
78
  uint32 versionCode = 10;
78
79
  string versionName = 11;
79
80
  string activity = 12;
81
+ uint32 user = 13;
80
82
  }
81
83
 
82
84
  message ApplicationProcess {
@@ -102,11 +104,13 @@ message HookRequest {
102
104
  DataEncode encode = 5;
103
105
  uint32 standup = 6;
104
106
  bool spawn = 7;
107
+ uint32 user = 8;
105
108
  }
106
109
 
107
110
  message HookRpcRequest {
108
111
  string package = 1;
109
112
  string callinfo = 2;
113
+ uint32 user = 3;
110
114
  }
111
115
 
112
116
  message HookRpcResponse {
@@ -52,10 +52,10 @@ service Application {
52
52
  rpc getIdentifierByLabel(String) returns (String) {}
53
53
 
54
54
  rpc callScript(HookRpcRequest) returns (HookRpcResponse) {}
55
- rpc isScriptAlive(String) returns (Boolean) {}
56
- rpc isScriptAttached(String) returns (Boolean) {}
55
+ rpc isScriptAlive(HookRequest) returns (Boolean) {}
56
+ rpc isScriptAttached(HookRequest) returns (Boolean) {}
57
57
  rpc attachScript(HookRequest) returns (Boolean) {}
58
- rpc detachScript(String) returns (Boolean) {}
58
+ rpc detachScript(HookRequest) returns (Boolean) {}
59
59
  }
60
60
 
61
61
  service Debug {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamda
3
- Version: 7.90
3
+ Version: 8.5
4
4
  Summary: Android reverse engineering & automation framework (Client API)
5
5
  Home-page: https://github.com/firerpa/lamda
6
6
  Author: rev1si0n
lamda-7.90/README.md DELETED
@@ -1,43 +0,0 @@
1
- <p align="center">
2
- <img src="image/logo.svg" alt="LAMDA" width="345">
3
- </p>
4
-
5
- <p align="center">安卓 RPA 机器人框架,下一代移动端数据自动化机器人</p>
6
-
7
- <p align="center">
8
- <img src="https://img.shields.io/badge/python-3.6+-blue.svg?logo=python&labelColor=yellow" />
9
- <img src="https://img.shields.io/badge/android-6.0+-blue.svg?logo=android&labelColor=white" />
10
- <img src="https://img.shields.io/badge/root%20require-red.svg?logo=android&labelColor=black" />
11
- <img src="https://img.shields.io/github/downloads/rev1si0n/lamda/total" />
12
- <img src="https://img.shields.io/github/v/release/rev1si0n/lamda" />
13
- </p>
14
-
15
- <p align="center"><a href="https://device-farm.com/doc/index.html">使用文档</a> | <a href="https://t.me/lamda_dev">TELEGRAM</a> | <a href="https://lamda.run/join/qq">QQ 群组</a> | <a href="https://github.com/rev1si0n/lamda/blob/HEAD/CHANGELOG.txt">更新历史</a></p>
16
-
17
- 智能机的崛起,传统网页端的普及度也开始显著减弱,数据与应用正加速向移动端转移。越来越多的人选择通过智能手机和平板等移动设备来获取信息和服务。随着移动设备的普及,用户享受到更便捷访问体验,传统的网页内容模式面临重新审视。与此同时,数据采集的技术也亟需适应这一趋势。过去,许多数据采集工具专注于网页内容,在移动端环境中,尤其是在移动端封闭的黑盒中,现今的常规采集技术也面临着新的挑战。LAMDA 的诞生,为这一切创造了可能。
18
-
19
- LAMDA 是**安卓领域的集大成者**,设计为减少**安全分析**及**应用测试**或**自动化**工作的时间和琐碎问题,经过超 500 台设备的生产环境考验,稳定应用于多个大型系统,包括自动化取证,云平台,数据采集,合规分析等,具备商业级软件的质量和稳定性,仅需 root 权限即可正常运行。具备 ARM/X86 全架构,安卓 6.0-14 的广泛兼容性,支持 **模拟器**、**真机**、**云手机**、 **WSA**(Windows Subsystem for Android™️)、**RK开发板** (所有 ARM 架构)以及 **Redroid** 等大多数运行安卓系统的设备。为**移动端 RPA 数据采集**提供稳定的解决方案,以**编程化**的**接口**替代大量手动操作,**易部署**,没有那些复杂花哨不跨平台的安装流程,你所需要的能力他大概率能做到并且做的更好。他并不是一个单一功能的框架,他是集 Appium、uiautomator **自动化**的超集同时具备**逆向**领域如 **Hook** **抓包** **证书安装** **组网** **API跟踪** **手机自控** 等等各种能力的框架。当然,LAMDA 可以做到的远不止于此,你可以阅读使用文档尽情探索他的所有能力。
20
-
21
-
22
-
23
- <h3><p align="center">丰富的设备编程接口</p></h3>
24
-
25
- <p align="center">提供多达 160 条编程 API 接口,让你可以对安卓设备进行无微不至的管理和操作,提供了包括命令执行,系统设置,系统状态,应用相关,自动化相关,代理以及文件等十几个大类的接口。同时提供了封装完整的 Python 库让你可以快速上手使用。</p>
26
-
27
- <h3><p align="center">简洁易用的远程桌面</p></h3>
28
-
29
- <p align="center">
30
- <img src="image/demo.gif" alt="动图演示" width="95%">
31
- </p>
32
-
33
- <h3><p align="center">一键中间人流量分析及更多其他功能</p></h3>
34
-
35
- 支持常规以及国际APP流量分析,DNS流量分析,得益于 [mitmproxy flow hook](https://docs.mitmproxy.org/stable/api/events.html),你可以对任何请求做到最大限度的掌控,mitmproxy 功能足够丰富,你可以使用 Python 脚本实时修改或者捕获应用的请求,也可以通过其 `Export` 选项导出特定请求的 `curl` 命令或者 `HTTPie` 命令,分析重放、拦截修改、功能组合足以替代你用过的任何此类商业/非商业软件。如果你仍不清楚 mitmproxy 是什么以及其具有的能力,请务必先查找相关文档,因为 LAMDA 将会使用 mitmproxy 为你展现应用请求。
36
-
37
- <p align="center">
38
- <img src="image/mitm.gif" alt="动图演示" width="95%">
39
- </p>
40
-
41
- <p align="center">
42
- 当然,LAMDA 提供的能力不止于这些,由于篇幅较长将不在此罗列,他是你强有力的设备控制及管理工具,如果你感兴趣,请转到 使用文档。
43
- </p>
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes