精华内容
下载资源
问答
  • Android滑块验证码控件
  • android 滑块和进度条控件使用代码
  • 小小滑块可笑可笑-安卓滑块验证码通杀方案研究(1) 直接点击即可前往访问。 前言 通常我们在做自动化任务时候,经常会遇到一些验证码验证。 其中遇到最多的还是滑块验证码,下面我们来单独探讨这个滑块的过程。 一些...

    说明

    文章首发于HURUWO的博客小站,本平台做同步备份发布。
    如有浏览或访问异常图片加载失败或者相关疑问可前往原博客下评论浏览。

    小小滑块可笑可笑-安卓滑块验证码通杀方案研究(1)

    直接点击即可前往访问。

    前言

    通常我们在做自动化任务时候,经常会遇到一些验证码验证。
    其中遇到最多的还是滑块验证码,下面我们来单独探讨这个滑块的过程。

    一些说明 因为滑块通常是拼图形式 或者是干脆就是从左到右的滑动就行。

    这里只重点讨论滑块的滑部分 关于识别滑动位置 需要单独开文章来讲解

    图中的例子

    由于CDN设置时间戳,图片可能失效,请前往原文地址浏览

    逆向抓包拦截方案(好用但不通用)

    核心思想就是对验证的页面进行逆向分析,根据上传的包信息。分析出具体滑动的参数,直接伪造一条滑动参数过去。

    服务器后台接收参数之后认为你已经滑动成功,代替手动滑过。

    但是要做的这一点需要极高的知识储备,需要很多的逆向知识。

    优点是很快 很有针对性

    缺点是

    1.难度大 通常还有很多的参数校验 需要一一破解

    2.不够通用也不够灵活 一个新的app或者新的滑块都需要重写全部逻辑

    所以我们探讨一种通用的 滑动协议 就是使用自动化的方式代替我们去滑动。

    自动化滑动方案(通用但是不够好)

    既然讨论的是滑动 当然就是关于如何自动化而不是手动,不然所有讨论都没有意义。

    关于自动化 类似的方案有:

    1.adb
    2.appium 测试框架 等 方案
    3.无障碍 类似auto.js 等 方案

    现在测试下三种方案的滑动代码

    1.adb 滑动代码

    adb shell input swipe 250 250 300 300
    

    指的就是从 250,250 滑动到 300,300 坐标 可以多段坐标移动 匀速的

    2.appium滑动代码

    关于appium 我用的不多,我只能直接从网上抓到一部分代码

    http://appium.io/ 文档里关于滑动这一块的:

    Android 4.3+: 谷歌的 UiAutomator / UiAutomator2Android 2.3+: 谷歌的 Instrumentation. (通过绑定独立的项目—— Selendroid 提供对 Instrumentation 的支持)

    因为appium是基于谷歌的测试框架的 所以逻辑类似:

    https://appium.io/docs/en/writing-running-appium/touch-actions/

    https://appium.io/docs/en/writing-running-appium/android/android-mobile-gestures/

    这是关于点击操作的文档地址

    关于滑动手势swipeGesture

    该手势在给定的元素/区域上执行滑动手势。自Appium v​​1.19起可用
    
    支持的参数
    elementId:要刷卡的元素的ID。如果缺少元素ID,则必须提供滑动边界区域。如果同时提供了元素ID和滑动边界区域,则该区域将被有效忽略。
    left:滑动边界区域的左坐标
    top:滑动边界区域的顶部坐标
    width:滑动边界区域的宽度
    height:滑动边界区域的高度
    方向:滑动方向。强制值。可接受的值为:up,down,left和right(不区分大小写)
    percent:滑动的大小占滑动区域大小的百分比。有效值必须是0..1范围内的浮点数,其中1.0是100%。强制值。
    speed:执行此手势的速度,以每秒像素为单位。该值不能为负。默认值为5000 * displayDensity
    

    代码示例:

    ((JavascriptExecutor) driver).executeScript("mobile: swipeGesture", ImmutableMap.of(
        "left", 100, "top", 100, "width", 200, "height", 200,
        "direction", "left",
        "percent", 0.75
    ));
    

    同样可以从a点移动到b点 速度也是匀速的。这里额外的有一个传入元素id功能,可以直接对应滑过指定控件,比adb更方便和高效一点。

    3.无障碍的滑动代码

    直接使用无障碍方式滑动,关于滑动这个动作。无障碍在7.0版本上新增了dispatchGesture 这个动作来来滑动。

    具体可以这样写:

    Path path1 = new Path();
                            path1.moveTo(x1, y1);
                            path1.lineTo(x1, y2);
     GestureDescription.Builder builder = new GestureDescription.Builder();
                            GestureDescription gestureDescription = builder
                                    .addStroke(new GestureDescription.StrokeDescription(path1, 0, 1000))
                                    .build();
                            service.dispatchGesture(gestureDescription, null, null);
    

    这就从x1滑动到了x2了,甚至可以多家几条path达到控制速度的调整。

                            int y1 = 800;
                            int y2 = 1000;
                            int x1 = 200;
                            int x2 = 400;
                            int x3 = 600;
                            int x4 = 800;
    
                            Path path1 = new Path();
                            path1.moveTo(x1, y1);
                            path1.lineTo(x1, y2);
    
                            Path path2 = new Path();
                            path2.moveTo(x1, y2);
                            path2.lineTo(x2, y2);
    
                            Path path3 = new Path();
                            path3.moveTo(x2, y2);
                            path3.lineTo(x4, y2);
    
                            GestureDescription.Builder builder = new GestureDescription.Builder();
                            GestureDescription gestureDescription = builder
                                    .addStroke(new GestureDescription.StrokeDescription(path1, 1000, 1000))
                                    .addStroke(new GestureDescription.StrokeDescription(path2, 1900, 1000))
                                    .addStroke(new GestureDescription.StrokeDescription(path3, 2800, 1000))
                                    .build();
                            service.dispatchGesture(gestureDescription, null, null);
    

    三条路径滑动 间隔连上就会变成一个了。但是系统做了限制,最多最多添加10条路径,否则会抛出异常。

    测试滑动验证效果

    自行编写的滑块验证码

    关于这一点 我为了方便快速测试,自己找了一些开源的验证码模块改了改。

    通过要求只有一点: 只要用户能从A划到B点末端就算成功

    三种方式的测试成功率都很高,因为这种简单的从左滑到右都是秒过的。

    至此大功告成,三种方案通杀了安卓客户端的验证码模块(我以为)

    第三方平台验证码

    这次挑了几个大厂的app 故意跑出来验证码:

    尝试直接滑过,结果就是虽然滑倒了指定的地方。但是直接返回了一个大大的失败二字。

    这里涉及的app有 快手 闲鱼 小红书等等几大平台。正因为我在做日常的闲鱼爬虫
    以及更多数据爬虫的时候会遇上这些烦人的滑块。

    验证结果:

    快手:失败 100%
    闲鱼:失败 100%
    小红书:失败 100%

    可知所有的app都能轻易的知道我是用自动化方式划过的,而且直接拒绝了这次的滑动验证请求。

    分析失败原因和解决思路

    失败原因:为何第三方app校验不通过

    在分析这个滑动校验原理的过程中,我发现了一个专门做滑动验证的厂商–极验

    http://www.geetest.com/

    由于CDN设置时间戳,图片可能失效,请前往原文地址浏览

    在他的安全风控里面我找到了一些有用的的信息:

    由于CDN设置时间戳,图片可能失效,请前往原文地址浏览

    原来这些验证平台不讲武德,直接配合大数据和AI判断了我的滑动轨迹。

    由于CDN设置时间戳,图片可能失效,请前往原文地址浏览

    这种匀速的滑动根本过不了验证平台的校验。

    类似的还有数美 同盾 网易等验证平台

    由于CDN设置时间戳,图片可能失效,请前往原文地址浏览

    解决方案:如何做出和真人一样的滑动

    首先可以认定的就是 那些普通的自动化工具只能做一些非常机械化的滑动,无论是匀速还是加速减速都显得非常的机械化。

    这种机械化的速度变化曲线会非常容易针对,只要做个简单的校验就可以拦住了。

    所以我们追求一个更加颗粒度的滑动方案,不是平滑的滑动。也不是一段一段的滑动,而是精确度粒度达到一像素一像素的程度才行。

    具体的策略如下:

    1. 生成符合规则的路径曲线 模仿人类的速度 抖动等参数

    2. 使用像素级别的颗粒度的滑动控制工具滑动界面滑块

    3. 调整 适配 再生成曲线 再调整 再适配 提高成功率到满意程度

    总结

    关于滑动验证码的探究方案到这里了,至于如何做出像素级别得到滑动看下下篇文章的分解。

    展开全文
  • 在 app 的 build.gradle 添加依赖implementation 'com.luozm.captcha:captcha:1.1.2'2.将 Captcha 添加至布局文件android:id="@+id/captCha"android:layout_centerInParent="true"android:layout_width="match_...

    先上图看看实现效果

    dc08715b7b4778e00a016f2891f5627f.png

    1.在 app 的 build.gradle 添加依赖

    implementation 'com.luozm.captcha:captcha:1.1.2'

    2.将 Captcha 添加至布局文件

    android:id="@+id/captCha"

    android:layout_centerInParent="true"

    android:layout_width="match_parent"

    android:layout_height="265dp"

    android:layout_marginRight="10dp"

    android:layout_marginLeft="10dp"

    app:mode="mode_bar"

    app:src="@drawable/validate"

    app:blockSize="50dp"

    android:scaleType="centerCrop"

    app:max_fail_count="4"/>

    3.添加 Java 代码

    public void showw(String advPic) {

    Context context = MainActivity.this;

    diaa = new Dialog(context, R.style.edit_AlertDialog_style);

    diaa.setContentView(R.layout.item_pict);

    captcha = diaa.findViewById(R.id.captCha);

    final Button btn_mode = diaa.findViewById(R.id.btn_mode);

    final Captcha captcha = diaa.findViewById(R.id.captCha);

    ImageView cuowu = diaa.findViewById(R.id.im_cuowu);

    // Glide.with(getApplication()).load(advPic).into(captcha );

    captcha.setBitmap(advPic);

    btn_mode.setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    if (captcha.getMode() == Captcha.MODE_BAR) {

    captcha.setMode(Captcha.MODE_NONBAR);

    btn_mode.setText("滑动条模式");

    } else {

    captcha.setMode(Captcha.MODE_BAR);

    btn_mode.setText("无滑动条模式");

    }

    }

    });

    cuowu.setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    diaa.dismiss();

    itData(mLongitude, mLatitude);

    }

    });

    captcha.setCaptchaListener(new Captcha.CaptchaListener() {

    @Override

    public String onAccess(long time) {

    Toast.makeText(MainActivity.this, "验证成功", Toast.LENGTH_SHORT).show();

    diaa.dismiss();

    diaa.setCanceledOnTouchOutside(true);

    return "验证通过";

    }

    @Override

    public String onFailed(int count) {

    Toast.makeText(MainActivity.this, "验证失败,失败次数" + count, Toast.LENGTH_SHORT).show();

    return "验证失败";

    }

    @Override

    public String onMaxFailed() {

    Toast.makeText(MainActivity.this, "验证超过次数,你的帐号被封锁", Toast.LENGTH_SHORT).show();

    return "可以走了";

    }

    });

    diaa.show();

    diaa.setCanceledOnTouchOutside(true);

    Window w = diaa.getWindow();

    WindowManager.LayoutParams lp = w.getAttributes();

    lp.x = 0;

    lp.y = 40;

    diaa.onWindowAttributesChanged(lp);

    }

    展开全文
  • 原文链接 小小滑块可笑可笑-安卓滑块验证码通杀方案研究3直接点击即可前往访问。 更多技术文章访问本人博客HuRuWo的技术小站,包括Android 逆向 app,闲鱼爬虫 微信爬虫 抖音爬虫 群控 等相关知识 也可关注公众号 ...

    说明

    文章首发于HURUWO的博客小站,本平台做同步备份发布。

    如有浏览或访问异常图片加载失败或者相关疑问可前往原博客下评论回复。

    原文链接 小小滑块可笑可笑-安卓滑块验证码通杀方案研究3直接点击即可前往访问。

    更多技术文章访问本人博客HuRuWo的技术小站,包括Android 逆向 app,闲鱼爬虫 微信爬虫 抖音爬虫 群控 等相关知识

    也可关注公众号 ‘wan_coder’ 第一时间收到文章更新

    前言

    本章继续研究滑块的对抗,来到了核心的轨迹生成部分

    录制工具的编写

    所谓录制工具其实就是记下时间点的坐标位置

    关于坐标位置的记录,请各位安卓开发人员自行复习:

    Android 事件传递机制详解

    事件顺序 Activity–> Window–>DecorView --> 布局View

    实体类point_time定义

    public class TimePoint {
        private long time;
        private float x;
        private float y;
    
        public TimePoint(long time, float x, float y) {
            this.time = time;
            this.x = x;
            this.y = y;
        }
    
        public long getTime() {
            return time;
        }
    
        public void setTime(long time) {
            this.time = time;
        }
    
        public float getX() {
            return x;
        }
    
        public void setX(float x) {
            this.x = x;
        }
    
        public float getY() {
            return y;
        }
    
        public void setY(float y) {
            this.y = y;
        }
    }
    

    保存point time

    触摸事件拦截记录

    public class MainActivity extends AppCompatActivity {
    
        ArrayList<TimePoint> timePoints = new ArrayList<>();
        long startTime = 0L;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        //事件顺序 Activity--> Window-->DecorView --> 布局View
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
    
            //从按下开始 0
            //从离开结束 1
    
            if(ev.getAction()==0){
                startTime = TimeUtils.getNowMills();
                timePoints.clear();
            }
            if(ev.getAction()==2){
                timePoints.add(new TimePoint(TimeUtils.getNowMills()-startTime,ev.getRawX(),ev.getRawY()));
            }
    
            if(ev.getAction()==1){
                timePoints.add(new TimePoint(TimeUtils.getNowMills()-startTime,ev.getRawX(),ev.getRawY()));
                String data = new Gson().toJson(timePoints);
                Log.e("xxx",data);
            }
    
            return super.dispatchTouchEvent(ev);
        }
    
    
    }
    

    核心就是dispatchTouchEvent方法中拦截事件记录下来

    测试生成的轨迹记录

    随便一滑

    [{"time":7,"x":180.83257,"y":1229.4462},{"time":39,"x":182.83072,"y":1229.4462},{"time":41,"x":194.08751,"y":1231.0153},{"time":55,"x":204.31084,"y":1231.9451},{"time":58,"x":222.06346,"y":1237.169},{"time":73,"x":238.27936,"y":1241.9404},{"time":75,"x":254.25331,"y":1247.2677},{"time":89,"x":268.2516,"y":1251.936},{"time":91,"x":285.22064,"y":1254.8489},{"time":106,"x":303.7188,"y":1257.9333},{"time":108,"x":325.78207,"y":1262.648},{"time":122,"x":344.68085,"y":1266.4294},{"time":124,"x":367.20758,"y":1271.279},{"time":139,"x":387.64105,"y":1275.9253},{"time":140,"x":412.6566,"y":1280.6907},{"time":158,"x":450.11096,"y":1286.1744},{"time":188,"x":504.03333,"y":1296.416},{"time":190,"x":551.3913,"y":1306.5754},{"time":206,"x":572.4699,"y":1310.4097},{"time":208,"x":595.25433,"y":1316.845},{"time":222,"x":617.4283,"y":1323.9038},{"time":224,"x":638.30457,"y":1330.0212},{"time":239,"x":660.88806,"y":1336.898},{"time":242,"x":677.3767,"y":1339.2922},{"time":273,"x":733.32104,"y":1354.8896},{"time":276,"x":748.3225,"y":1358.791},{"time":291,"x":763.79285,"y":1361.8865},{"time":294,"x":779.26654,"y":1366.5145},{"time":305,"x":793.765,"y":1370.3826},{"time":306,"x":806.70953,"y":1374.2257},{"time":321,"x":819.74097,"y":1376.8799},{"time":322,"x":833.0282,"y":1380.0782},{"time":339,"x":844.2183,"y":1382.8772},{"time":342,"x":853.7906,"y":1383.8988},{"time":357,"x":873.35693,"y":1387.523},{"time":372,"x":881.68365,"y":1389.3743},{"time":373,"x":887.5774,"y":1389.9404},{"time":388,"x":893.173,"y":1390.8734},{"time":389,"x":896.481,"y":1391.9508},{"time":406,"x":900.16656,"y":1392.8726},{"time":410,"x":903.26733,"y":1392.9243},{"time":422,"x":905.1619,"y":1393.8721},{"time":425,"x":905.6614,"y":1394.8718},{"time":427,"x":905.16187,"y":1394.372}]
    

    如果要指定滑动距离 只需要做好位置标记即可,

    假设生成了100条从

    100-200到100-1000之间的轨迹记录,接下来在复用轨迹记录的时候。

    比较要滑动的距离离哪个最近 就用哪个去匹配即可。

    总结

    轨迹记录工具源代码放在仓库https://github.com/HuRuWo/KillerAndroidSlide

    接下来一节就是实战滑动

    展开全文
  • android-slidr另一个android滑块/ seekbar,但有所不同:-)下载依赖项{编译'com.github.florent37:android-slidr:1.0.4'} <com.github.florent37.androidslidr.Slidr android-slidr另一个android滑块/ seekbar,...
  • 原文链接 小小滑块可笑可笑-安卓滑块验证码通杀方案研究5直接点击即可前往访问。 更多技术文章访问本人博客HuRuWo的技术小站,包括Android 逆向 app,闲鱼爬虫 微信爬虫 抖音爬虫 群控 等相关知识 也可关注公众号 ...

    说明

    文章首发于HURUWO的博客小站,本平台做同步备份发布。

    如有浏览或访问异常图片加载失败或者相关疑问可前往原博客下评论回复。

    原文链接 小小滑块可笑可笑-安卓滑块验证码通杀方案研究5直接点击即可前往访问。

    更多技术文章访问本人博客HuRuWo的技术小站,包括Android 逆向 app,闲鱼爬虫 微信爬虫 抖音爬虫 群控 等相关知识

    也可关注公众号 ‘wan_coder’ 第一时间收到文章更新

    前言

    之前所有的测试都变得无效了,无法完成

    action_down
    action_move 随机耗时
    action_move 随机耗时
    action_move 随机耗时
    action_move 随机耗时
    action_up
    

    的一系列的连续事情事情

    回到系统源码

    有句老话 没有什么是阅读系统源码解决不了的。关于点击触发事件的核心在于

    几个核心类方法:

    public boolean onTouchEvent(MotionEvent event);

    public boolean dispatchTouchEvent(MotionEvent ev);

    public boolean onTouch(View v, MotionEventevent);

    ①onTouchEvent(MotionEvent event)是View中定义的方法,而且是Public类型,所以Activity、ViewGroup、View均可以调用这个方法,最常见的关于这块的知识点在Android事件分发中,onTouchEvent()是每个事件处理对象都有的方法,用于根据下层的onTouchEvent()返回值类型判断是否调用,最常见的用法是自定义View时写入到view中,从而让该View获取用户对手机屏幕的各种操作,并对不同类型的操作实现不同的反馈,属于一个宏观的屏幕触摸监控方法;

    ②onTouch((View v, MotionEvent event)是View.OnTouchListener接口中实现的唯一方法,接收两个参数,第二个参数是之前提过的event事件对象,第一个参数是一个具体的view类型对象,这就意味着onTouch()方法必须和某个控件进行绑定,即某个控件实现了View.OnTouchListener接口,才能调用onTouch()方法。

    我们可以拿到当前的view对象或者activity直接调用这些方法触发事件

    展开全文
  • 原文链接 小小滑块可笑可笑-安卓滑块验证码通杀方案研究2直接点击即可前往访问。 更多技术文章访问本人博客HuRuWo的技术小站,包括Android 逆向 app,闲鱼爬虫 微信爬虫 抖音爬虫 群控 等相关知识 也可关注公众号 ...
  • 原文链接 小小滑块可笑可笑-安卓滑块验证码通杀方案研究4直接点击即可前往访问。 更多技术文章访问本人博客HuRuWo的技术小站,包括Android 逆向 app,闲鱼爬虫 微信爬虫 抖音爬虫 群控 等相关知识 也可关注公众号 ...
  • Android滑块拼图验证码控件

    千次阅读 2019-05-18 08:55:45
    https://github.com/luozhanming/Captcha Android滑块拼图验证码控件 https://blog.csdn.net/sdfsdfdfa/article/details/79120665 Android拼图滑块验证码控件 ...
  • 先上图看看实现效果 1.在 app 的 build.gradle 添加依赖implementation ...将 Captcha 添加至布局文件android:id="@+id/captCha"android:layout_centerInParent="true"android:layout_width="match_parent"...
  • Android滑块开关

    千次阅读 2017-07-23 16:35:56
    Android滑块开关网上已经有很多,我找了好多但是我总觉得都不实用,而且实现也不够简洁不利于维护。于是我把自己以前写的Demo拿出来改了一下使用,也分享给需要的小伙伴,希望对别人有所启发。里面包含自定义View的...
  • Android 滑块验证

    千次阅读 2018-10-28 00:46:00
    先上图看看实现效果 1.在 app 的 build.gradle 添加依赖 implementation 'com.luozm.captcha:captcha:1.1.2' 2.将 Captcha 添加至布局文件 <... android:id="@+id/captCha" a...
  • Android滑块底部引导菜单

    千次阅读 2013-07-19 16:11:08
    最近做Android项目自己封装了一个滑动的引导菜单,在此拿来跟大家分享 废话不多说,上效果图: SlideGuideMenu.java 是这个封装的类,继承了RadioGroup,自定义了三个属性:menuIcons,menuNames,...
  • 滑动拼图验证码一般我们在网站上可以经常见到,本篇文章给大家介绍该效果在android端的是如何实现首先看一下效果图:* 新建自定义view DragImageView主要方法:* 设置图片、滑块资源,设置图片、滑块之间的比例大小*...
  • 6 android 滑块和进度条

    千次阅读 2011-04-12 19:48:00
    目录结构 <br />  第一步: layout/progress_bar_layout.xml <?xml version="1.0" encoding="utf-8"?> xmlns:android=... android:layout_width="fill_p
  • 1、string.xml文件当前进度:%s当前进度:20%2、布局文件 bar.xmlandroid:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="10dip">android:id=...
  • android 滑块android seekBar Demo,可以调节音量等,可自己更换图片。
  • 安卓 android seekbar 自定义滑块 适合做音量调节 比较漂亮 我的资源汇总:http://blog.csdn.net/u013506037/article/details/39210793

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,491
精华内容 2,996
关键字:

安卓滑块