更多>>关于我们
西安鲲之鹏网络信息技术有限公司从2010年开始专注于Web(网站)数据抓取领域。致力于为广大中国客户提供准确、快捷的数据采集相关服务。我们采用分布式系统架构,日采集网页数千万。我们拥有海量稳定高匿HTTP代理IP地址池,可以有效获取互联网任何公开可见信息。
您只需告诉我们您想抓取的网站是什么,您感兴趣的字段有哪些,你需要的数据是哪种格式,我们将为您做所有的工作,最后把数据(或程序)交付给你。
数据的格式可以是CSV、JSON、XML、ACCESS、SQLITE、MSSQL、MYSQL等等。
更多>>技术文章
-
西安鲲之鹏
发布时间:2024-05-25 21:42:29
【经验分享】发现Frida Python库的enumerate_applications()在遍历APP时获取进程id存在主次不分的问题,导致后续attach到错误的进程。
例如图1所示,ctrip.android.view这个APP存在三个进程,其中第一个7928 才是主进程,其余两个是子进程,我们需要attach的是7928这个主进程才对。
但是如图2所示,enumerate_applications()把ctrip.android.view的进程id识别成8269了(ctrip.android.view:pushsdk.v1这个子进程),如果attach这个进程目标就跑偏了(各种类都找不到)。
解决方法:不要使用enumerate_applications(),自己读取ps的结果,拿到主进程id。
Frida版本16.2.1。
-
西安鲲之鹏
发布时间:2024-05-21 21:01:16
【经验分享】Frida获取RegisterNatives动态注册的JNI函数的地址
背景:某JNI的native函数在so的导出表中找不到,说明不是静态注册的,是通过RegisterNatives动态注册的(示例:https://blog.csdn.net/qq_29848853/article/details/129375219)。
可以使用Frida HOOK libart.so中的RegisterNatives函数,来曝出JNI函数的详细信息。
function hook_RegisterNatives() {
var symbols = Module.enumerateSymbolsSync("libart.so");
var addrRegisterNatives = null;
for (var i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
//_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
if (symbol.name.indexOf("art") >= 0 &&
symbol.name.indexOf("JNI") >= 0 &&
symbol.name.indexOf("RegisterNatives") >= 0 &&
symbol.name.indexOf("CheckJNI") < 0) {
addrRegisterNatives = symbol.address;
console.log("RegisterNatives is at ", symbol.address, symbol.name);
}
}
if (addrRegisterNatives != null) {
Interceptor.attach(addrRegisterNatives, {
onEnter: function (args) {
console.log("[RegisterNatives] method_count:", args[3]);
var env = args[0];
var java_class = args[1];
var class_name = Java.vm.tryGetEnv().getClassName(java_class);
//console.log(class_name);
var methods_ptr = ptr(args[2]);
var method_count = parseInt(args[3]);
for (var i = 0; i < method_count; i++) {
var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));
var name = Memory.readCString(name_ptr);
var sig = Memory.readCString(sig_ptr);
var find_module = Process.findModuleByAddress(fnPtr_ptr);
console.log("[RegisterNatives] java_class:", class_name, "name:", name, "sig:", sig, "fnPtr:", fnPtr_ptr, "module_name:", find_module.name, "module_base:", find_module.base, "offset:", ptr(fnPtr_ptr).sub(find_module.base));
}
}
});
}
}
setImmediate(hook_RegisterNatives);
代码来源:https://github.com/lasting-yang/frida_hook_libart
-
西安鲲之鹏
发布时间:2024-05-15 10:17:51
【经验分享】Frida 12不支持String.replaceAll。同一个脚本在16下工作正常,在12下就提示“TypeError: undefined not callable (property 'replaceAll' of ....”异常。
这是ChatGPT给出的解释:
在 Frida 12 中,原生的 String.prototype.replaceAll 方法可能无法使用,因为 Frida 12 使用的 JavaScript 引擎可能不支持 ECMAScript 2021(ES12)中的新特性。
这是ChatGPT给出的解决方案:
// 如果你的目标环境不支持 replaceAll,你可以自己实现一个类似的函数。以下是一个简单的实现:
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function (search, replacement) {
var target = this;
return target.split(search).join(replacement);
};
}
// 示例用法
var str = "Hello World! World is beautiful.";
var newStr = str.replaceAll("World", "Earth");
console.log(newStr); // 输出 "Hello Earth! Earth is beautiful."
-
西安鲲之鹏
发布时间:2024-05-13 10:16:42
【经验分享】通过Hook Java层的System.loadLibrary()来屏蔽某so的加载
var System = Java.use('java.lang.System');
const Runtime = Java.use('java.lang.Runtime');
const VMStack = Java.use('dalvik.system.VMStack');
System.loadLibrary.overload('java.lang.String').implementation = function(library){
console.log('[F] System.loadLibrary() called! library = "' + library + '"');
// 如果要屏蔽某个so的加载,直接return即可
// if(library.indexOf("msaoaidsec") !=-1){
// console.log('Bypass loading ' + library);
// return;
// }
return Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), library);
}
顺便吐槽一下,这个APP搞区别对待啊,Google渠道安装的默认不做加固啊。
-
西安鲲之鹏
发布时间:2024-05-13 09:42:36
【经验分享】Frida打印android so的加载顺序
function readStdString(str) {
const isTiny = (str.readU8() & 1) === 0;
if (isTiny) {
return str.add(1).readUtf8String();
}
return str.add(2 * Process.pointerSize).readPointer().readUtf8String();
}
var mod_art = Process.findModuleByName("libart.so");
if (mod_art) {
for (var exp of mod_art.enumerateExports()) {
if (exp.name.indexOf("LoadNativeLibrary") != -1) {
console.log(exp.name, exp.address);
Interceptor.attach(exp.address, {
onEnter: function (args) {
this.sopath = readStdString(args[2]);
console.log("[ [LoadNativeLibrary] sopath = ", this.sopath);
},
onLeave: function (retval) {
//console.log("[ [LoadNativeLibrary] out sopath = ", this.sopath);
}
});
break;
}
}
}
如下图示例,该APP在加载libmsaoaidsec.so之后退出了,说明frida检测机制在这个so中。
-
西安鲲之鹏
发布时间:2024-05-12 17:22:18
【经验分享】Frida “Error: java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare()” 问题的解决。
使用Java.scheduleOnMainThread(fn)将代码安排在主线程执行即可,例如下完整示例,实现 显示Toast提示。
function toast(text){
// 显示Toast提示
Java.perform(function() {
Java.scheduleOnMainThread(function(){
var Toast = Java.use('android.widget.Toast');
var context = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
var CharSequence = Java.use('java.lang.CharSequence')
var String = Java.use('java.lang.String')
Toast.makeText(context, Java.cast(String.$new(text), CharSequence), Toast.LENGTH_SHORT.value).show();
});
});
}
-
西安鲲之鹏
发布时间:2024-05-10 11:17:13
【经验分享】推荐一款好用的鼠标轨迹记录器 - MouseController(https://sourceforge.net/projects/mousecontroller/)。支持动作录制重放。另外,还有一个类似的工具,叫做KeymouseGo,它不光能记录鼠标动作,还能记录键盘动作,项目地址:https://github.com/taojy123/KeymouseGo。 -
西安鲲之鹏
发布时间:2024-03-12 11:51:28
-
西安鲲之鹏
发布时间:2024-02-23 13:00:33
【经验分享】Frida里Java.choose找到某个类的实例,在调用该实例方法时出现“script should be invoke on MainThread”问题的解决:
// Assign the javascript code to a variable.
jsCode = """
// Create a method called Cheese that will be exported.
function Cheese()
{
// Perform the code from injected context.
Java.perform(function ()
{
// Variable to store the view representing the button
// to click programmatically.
var view;
// Define the Runnable type javascript wrapper.
var Runnable = Java.use("java.lang.Runnable");
// Find the MainActivity class in myApp.
Java.choose("com.example.myApp.MainActivity",
{
// Once it has been found execute the following code.
onMatch: function(instance)
{
// Get the view representing button to click.
// 2131436712 id derived from decompiling app.
view = instance.findViewById(2131436712);
// Define a new class that implements Runnable and provide
// the implementation of the run() method which, will
// execute from the Main thread.
const MyRunnable = Java.registerClass({
name:'com.example.MyRunnable',
implements: [Runnable],
methods: {
// run executes button click.
run(){
instance.onClick(view);
},
}
});
// Create an instance of the class just created.
var MyGuiUpdate = MyRunnable .$new();
// Schedule the run method in MyGuiUpdate to
// execute on the UI thread.
instance.runOnUiThread(MyGuiUpdate );
},
onComplete:function(){}
});
解决方法来源:https://stackoverflow.com/questions/65790594/calling-an-api-to-modify-an-apps-gui-from-non-main-thread-in-frida -
西安鲲之鹏
发布时间:2024-02-21 21:45:47
【经验分享】Frida script中如何给Java的Long类型变量赋值?
例如,某Java类中有如下Long类型变量定义:
/* renamed from: e */
public Long f90137e;
尝试修改e的值,依次做如下测试:
(1)classObj.e.value = 1978705204; 会报"Error: Expected value compatible with java.lang.Long"错误。
(2)classObj.e.value = Java.use('java.lang.Long').parseLong.overload('java.lang.String').call(Java.use('java.lang.Long'), "1978705204");依然会报上述错误。
(3)这个方法可以成功赋值:classObj.e.value = Java.use('java.lang.Long').$new(1978705204); -
西安鲲之鹏
发布时间:2024-02-21 19:01:04
【经验分享】miller使用filter查询条件,当遇到字段含有空格或者其它特殊字符时怎么处理?如下示例中某个字段含有点号,直接查询会报错。解决方法如下:
示例:mlr --icsv --oxtab --from mouser_products_202312.csv filter '${Mfr.}=~"TDK" || ${Brand}=~"TDK"' then count
使用Pandas时,也有类似问题,解决方法:
df[df['Brand'].str.contains("TDK")|df['Mfr.'].str.contains("TDK")]
另外,Stackoverflow(https://stackoverflow.com/questions/50697536/pandas-query-function-not-working-with-spaces-in-column-names)上有人说可以用`字段`将字段包裹起来,例如:a.query('`a b` == 5') ,但是需要Pandas是0.25版本,我机器上是0.24.2,测试没有效果。