1 | yum install -y ppp wget net-tools perl |
参考:
1 | yum install -y ppp wget net-tools perl |
参考:
在阅读本文之前,假设你的手机已经root,并且已经成功安装好了 XposedInstaller。
Xposed 是一个 Android 平台上的动态劫持框架,通过替换手机上的孵化器 zygote 进程为 Xposed 自带的 zygote,使其在启动过程中加载 XposedBridge.jar,模块开发者可以通过 jar 提供的 API 来实现对所有的 Function(这里可以理解为方法) 的劫持,在原 Function 执行的前后加上自定义代码。
Xposed框架是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。Xposed理论上能够hook到系统任意一个Java进程,由于是从底层hook,所以需要root权限,并且每次更新都要重新启动,否则不生效 。
这两个框架都是app注入的利器,只是相对来说有各自特点罢了。Cydia Substrate是一个代码修改平台。它可以修改任何主进程的代码,不管是用Java还是C/C++(native代码)编写的。而Xposed只支持 hook system/bin/app_process中的Java函数。其实Cydia Substrate 与xposed 的hook原理是一样的,二者都可以作为Java Hook的框架,看使用习惯了(iOS的越狱用到的便是Cydia Substrate)。笔者最近研究主要以Xposed为主,暂不对Cydia Substrate进行详细的说明,后续有研究会继续以文字形式记录吧。
Xposed的运用太过广泛,作为这个系列的第一篇笔记,这里也介绍一种Xposed最简单的应用场景。
我们修改入门android逆向的项目,将 Hello World
修改为 Hello Xposed!
a. 随意在Android Studio里创建一个项目,在这里我的包名是:com.blues.cracktest 里面没有任何后续添加的代码,编译之后只有屏幕中间最经典的“Hello World!”;
b. 我们需要做的就是通过Xposed去修改这个“Hello World”,让它替换成任何我们想要它显示成为的东西,比如我期望是“Hello Xposed! ”
首先第一步先进行配置,在清单文件AndroidManifest里 Application作用域里加上如下配置:
1 | <meta-data |
第二步,在main目录下(java、res同级目录)创建assets文件夹,在该文件夹下新建一个xposed_init文件(该文件名称固定为xposed_init),该文件用于放置hook的入口,里面是一个路径(比如我的是com.example.androidrefirst.XposedInit,XposedInit就是我hook的入口,这个类后面会提及)。
第三步,新建一个类,这里就叫它XposedInit好了,让它实现(implements) IXposedHookLoadPackage 这个接口 ,重写 handleLoadPackage 方法(该方法用于获取需要hook到的类,里面会用到一个findAndHookMethod 用于hook对应的方法),我就直接show code吧:
1 | package com.example.androidrefirst; |
原来的MainActivity长这样:
1 | package com.example.androidrefirst; |
运行之后在 XposedInstaller 中启用我们的xposed模块 重启之后看效果。可以看到Hello Xposed!!!!!!!
参考:
逆向工程(又称逆向技术),是一种产品设计技术再现过程,即对一项目标产品进行逆向分析及研究,从而演绎并得出该产品的处理流程、组织结构、功能特性及技术规格等设计要素,以制作出功能相近,但又不完全一样的产品。逆向工程源于商业及军事领域中的硬件分析。其主要目的是在不能轻易获得必要的生产信息的情况下,直接从成品分析,推导出产品的设计原理。
逆向工程可能会被误认为是对知识产权的严重侵害,但是在实际应用上,反而可能会保护知识产权所有者。例如在集成电路领域,如果怀疑某公司侵犯知识产权,可以用逆向工程技术来寻找证据。
这里我们以安卓项目开始探索逆向工程之路
工欲善其身,必先利其器。
新建一个项目,名字是 Androidrefirst,实现的逻辑是在输入框内填写 2019之后 点击按钮跳转到成功页面。
主要代码如下
1 | package com.example.androidrefirst; |
生成 apk安装包 app-release.apk
需要用到的是dex2jar包里面的三个文件(当前是在windows环境下,Mac环境用对应的.sh文件):
d2j_invoke.bat
d2j-dex2jar.bat
lib
将这三个文件复制到一个空的文件夹内,将刚才.apk解压后的classes.dex文件也一起复制到这里
可以看到我们的代码
1 | package com.example.androidrefirst; |
对照着自己的手写的代码,已经差不离十了,对于想要代码思路的我们来说,到这里已经基本可以摸透他的逻辑。
apktool下载后会有两个文件,一个.jar(例如apktool_2.3.3.jar 需要把名字改成apktool.jar) 一个apktool.bat 。
同刚才一样在cmd命令下进入刚才文件夹(同样可以新建一个),连同我们刚才那个后缀为apk的安装包一起放入,输入如下命令
1 | apktool d app-release.apk # 此处app-release为apk名称 |
得到一个新的app-release(对应apk名称)文件夹
这个app-release文件夹下会得到若干文件,主要内容介绍如下:
修改原代码逻辑
我们只需要修改if后面的判断条件,设置为否即可if (!MainActivity.this.code.…),这样就成功绕过了条件约束。
接下来还有一部很重要那就是修改smali文件,找到MainActivity$1.smali这个文件用代码查看工具打开
找到这个if-eqz 修改成if-nez (nez对应为非,符号“!”),到这里要修改的部分都成功了,最后一步要做的就是重新打包了。当然对smali语法感兴趣的可以一起探讨学习。
在apktool文件夹路径的cmd下输入:
1 | apktool b [文件夹] -o test2.apk #(test2为新apk名称,[文件夹]为对应的有修改需要打包的文件夹) |
至此,我们的目标apk文件已经生成,当然如果你想装到你自己手机上还需要重新签名一下。
首先我们需要一个用于签名的.keystore文件,生成命令如下(这里我们假设生成的是demo.keystore)。
1 | keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore |
这里我们利用Java JDK提供的一个jarsigner进行签名,在刚才的cmd下继续操作,输入:
1 | jarsigner -verbose -keystore demo.keystore test2.apk demo.keystore |
以上。我们目的apk已经可以投入使用,如果需要更快更好的体验还需要进行一次字节对齐的操作(后续分析)。
参考:
IdentityServer4是一个用于ASP.Net Core的OpenID Connect和OAuth 2.0框架
通过使用 IdentityServer4 你可以
可以为你的应用(如网站、本地应用、移动端、服务)做集中式的登录逻辑和工作流控制。IdentityServer是完全实现了OpenID Connect协议标准。
在各种类型的应用上实现单点登录登出。
为各种各样的客户端颁发access token令牌,如服务与服务之间的通讯、网站应用、SPAS和本地应用或者移动应用。
支持来自Azure Active Directory, Google, Facebook这些知名应用的身份认证,可以不必关心连接到这些应用的细节就可以保护你的应用
我们先来一个基础的应用场景,保护我们的Api资源
在这个场景中我们定义一个IdentityServer服务,一个API的客户端,一个要访问这个api的客户端。
验证是否成功是从IdentityServer获取一个访问令牌,然后用这个令牌来获得Api的访问权限。
我们将要保护的资源定义在 Scopes 中,这是我们命名是 api1
1 | public static IEnumerable<ApiResource> GetApiResources() |
定义能够访问api的客户端。
我们使用客户端密码(Client Secret)来认证
1 | public static IEnumerable<Client> GetClients() |
Startup.cs中配置上IdentityServer
为了让 IdentityServer 使用你的 Scopes 和 客户端 定义,你需要向 ConfigureServices 方法中添加一些代码。你可以使用便捷的扩展方法来实现 —— 它们在幕后会添加相关的存储和数据到 DI 系统中:
1 | public void ConfigureServices(IServiceCollection services) |
这个时候访问 http://localhost:5000/.well-known/openid-configuration 可以看到 发现文档
新建一个站点并添加控制器
1 | [Route("identity")] |
将 IdentityServer4.AccessTokenValidation NuGet 程序包添加到你的 API 项目
然后添加中间件
1 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) |
1 | public void ConfigureServices(IServiceCollection services) |
将站点启动地址设置为 http://localhost:5001
这个时候,启动访问 http://localhost:5001/identity 可以看到401错误信息,说明访问还没有授权。
我们来编写一个客户端来请求访问令牌,然后使用这个令牌来访问 API。为此你需要为你的解决方案添加一个控制台应用程序。
IdentityServer 上的令牌端点实现了 OAuth 2.0 协议,你应该使用合法的 HTTP 来访问它。然而,我们有一个叫做 IdentityModel 的客户端库,它将协议交互封装到了一个易于使用的 API 里面。
添加 IdentityModel NuGet 程序包到你的客户端项目中。
1 | static async System.Threading.Tasks.Task Main(string[] args) |
我们同时启动三个项目,可以看到 http://localhost:5001/identity 返回的结果内容被正常的打印在控制台。
默认情况下访问令牌将包含 scope 身份信息,生命周期(nbf 和 exp),客户端 ID(client_id) 和 发行者名称(iss)
我们现在使用 客户端发送用户名和密码到令牌服务并获得一个表示该用户的访问令牌 access_token
为了方便演示 我们直接使用IdentityServer中的TestUser 类型表示一个测试用户及其身份信息。让我们向配置类(如果你有严格按照顺序进行演练,那么配置类应该在 QuickstartIdentityServer 项目的 Config.cs 文件中)中添加以下代码以创建一对用户
1 | public static List<TestUser> GetUsers() |
然后将测试用户注册到 IdentityServer
1 | public void ConfigureServices(IServiceCollection services) |
AddTestUsers 扩展方法在背后做了以下几件事:
1 | new Client |
客户端看起来跟之前 客户端凭证授权 的客户端是相似的。主要差别在于现在的客户端将会以某种方式收集用户密码,然后在令牌请求期间发送到令牌服务。
1 | using (var client = new HttpClient()) |
当你发送令牌到身份 API 端点的时候,你会发现与客户端凭证授权
相比,资源所有者密码授权有一个很小但很重要的区别。访问令牌现在将包含一个 sub 信息,该信息是用户的唯一标识。sub 信息可以在调用 API 后通过检查内容变量来被查看,并且也将被控制台应用程序显示到屏幕上。
sub 信息的存在(或缺失)使得 API 能够区分代表客户端的调用和代表用户的调用
OpenID Connect 1.0是OAuth 2.0协议之上的一个简单的身份层。 它允许客户端基于授权服务器执行的身份验证来验证最终用户的身份,以及以可互操作和类似REST的方式获取关于最终用户的基本配置文件信息。 OpenID Connect允许所有类型的客户端(包括基于Web的移动和JavaScript客户端)请求和接收关于认证会话和最终用户的信息。 规范套件是可扩展的,允许参与者使用可选功能,例如身份数据的加密,OpenID提供商的发现和会话管理
OpenID Connect 在OAuth2上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议。我们都知道OAuth2是一个授权协议,它无法提供完善的身份认证功能,OpenID Connect 使用OAuth2的授权服务器来为第三方客户端提供用户的身份认证,并把对应的身份认证信息传递给客户端,且可以适用于各种类型的客户端(比如服务端应用,移动APP,JS应用,winform应用),且完全兼容OAuth2,也就是说你搭建了一个OpenID Connect 的服务后,也可以当作一个OAuth2的服务来用。
IdentityServer提供了 可以快速创建UI的脚本 https://github.com/IdentityServer/IdentityServer4.Quickstart.UI
然后在start.cs中
1 | using System; |
注意现在的中的Clients添加一个client
1 | // mvc client, authorization code |
接下来你将向解决方案添加一个 MVC 应用程序,可以使用 ASP.NET Core “Web 应用程序” 模板来实现。 将应用程序配置为使用 5002 端口(可以查看概览部分以了解如何配置)。
为了能向 MVC 应用程序添加 OpenID Connect 认证支持,请添加如下 NuGet 程序包:
Microsoft.AspNetCore.Authentication.Cookies
Microsoft.AspNetCore.Authentication.OpenIdConnect
mvc的client的start.cs如下
1 | using System; |
现在我们多启动项目,看到mvcclient自动跳转到 ids网站,输入testuser的账号密码之后看到如下界面
Yes,Allow
然后我们看到看到跳转到了
到此我们的 基本 OpenID Connect 的用户认证完成
接下来我们以Google身份认证为例,添加对Google的支持
首先我们需要在Google的开发人员控制台申请 OAuth 2.0 客户端 ID
回调地址填写 http://localhost:5000/signin-google
然后在ids中添加nuget引用 Microsoft.AspNetCore.Authentcation.Google 到项目中
然后我们在中间件中添加引用
1 | services.AddAuthentication() |
注意:在 ASP.NET Core Identity 中使用外部认证的时候,SignInScheme 必须设置为 Identity.External,而不是 IdentityServerConstants.ExternalCookieAuthenticationScheme。
再次运行项目可以看到登录页面是多了个Google按钮。
通过认证后,你可以看到现在的身份信息是由 Google 数据提供的了。
你可以使用 QQ认证,微信认证等来实验 IdentityServer4的神奇之处。
当然 你也可以在 https://github.com/IdentityServer/IdentityServer4/tree/master/samples 中看到更多开源的例子。
Quartz.Net是根据Java的Quartz用C#改写而来,源码在https://github.com/quartznet/quartznet 。主要作用是做一些周期性的工作,或者定时工作。比如每天凌晨2点对前一天的数据统计。
我们需要明白 Quartz 的几个核心概念,这样理解起 Quartz 的原理就会变得简单了。
Job 表示一个工作,要执行的具体内容。
JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。
Trigger 代表一个调度参数的配置,什么时候去调。
触发器常用的有两种:SimpleTrigger触发器和CronTrigger触发器。
1 | var trigger = TriggerBuilder.Create() |
举例
1 | var trigger = TriggerBuilder.Create() |
Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。
以WebApi项目举例,用VS脚手架功能新建WebApi项目。
注册ISchedulerFactory的实例
1 | // This method gets called by the runtime. Use this method to add services to the container. |
Controller中
1 | using System; |
MyJob
1 | using Quartz; |
可以看到在error.log中输出结果
1 | 2020-04-17 11-55-45 |
你可以给Job增加参数
1 | var trigger3 = TriggerBuilder.Create() |
1 | IJobDetail job = JobBuilder.Create<MyJob>() |
在job中获取参数
1 | public class MyJob : IJob |
当Job中的参数和Trigger中的参数名称一样时,用 context.MergedJobDataMap获取参数时,Trigger中的值会覆盖Job中的值。
1 | [PersistJobDataAfterExecution]//更新JobDetail的JobDataMap的存储副本,以便下一次执行这个任务接收更新的值而不是原始存储的值 |
上面的例子是在api中使用Quartz
你也可以在 startup.cs中注册代码
1 | public void ConfigureServices(IServiceCollection services) |
或者在 HostedService
中注册代码
1 | public class HostedService : IHostedService |
参考:
https://www.cnblogs.com/MicroHeart/p/9402731.html
https://www.cnblogs.com/dangzhensheng/p/10496278.html
Consul是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,而且开发使用都很简便。它提供了一个功能齐全的控制平面,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心。
Consul是用Go开发的分布式服务协调管理的工具,它提供了服务发现,健康检查,Key/Value存储等功能,并且支持跨数据中心的功能。consul提供的一些关键特性:
- service discovery:consul通过DNS或者HTTP接口使服务注册和服务发现变的很容易,一些外部服务,例如saas提供的也可以一样注册。
- health checking:健康检测使consul可以快速的告警在集群中的操作。和服务发现的集成,可以防止服务转发到故障的服务上面。
- key/value storage:一个用来存储动态配置的系统。提供简单的HTTP接口,可以在任何地方操作。
- multi-datacenter:无需复杂的配置,即可支持任意数量的区域。
其实服务注册与发现的原理很简单。
当我们在本机运行Consul时,他会自动监听8500端口;然后我们通过一个开源类库(这个开源类库可以在nuget上检索到,文章下面会介绍),调用其下不同的方法来向这个Consul进程发送TCP消息,来注册服务或者发现服务。
Consul进程在接收到注册消息时,就把注册的服务信息存储到本地磁盘或内存(因为我没有具体去调查Consul存储数据是否使用了数据库,但我们都知道数据库的数据也是保存在本地磁盘的,所以,它肯定是把数据存进磁盘或者内存中了)。
Consul存储数据的地方,官方为其命名为数据中心,也就是上面说的保存我们注册的服务信息的本地磁盘或者内存。
Consul的集群也很好理解,在我们成功启动Consul以后,它除了监听8500端口以外,它还监听了一个8031端口。
这个8031端口就是用于Consul集群相互通信的。
我们都知道集群是要两台以上的电脑的,所以,我们就必须找到两台或以上的电脑安装Consul中间件。
然后,使用Consul的命令行,将两台电脑连接到一起,这样集群就形成了。
在集群内每台电脑上安装的Consul中间件,我们统称为服务器代理(Agent);当集群启动后,会在多个代理服务器之间选举出一个Leader。
选举Leader自然就是服务器代理之间的通信了,也就是通过上面提到的8031端口通信的。
选举了Leader,服务器代理就可以将自身的负载信息发送给Leader了,这样客户端调用Consul检索服务数据时,就可以去性能最优的那台机器上获取信息了。(注:这个就是举例说明,并非Consul的负载均衡的真实处理模式)
我们新建一个 api Service
在 startup.cs 中的 Configure 增加如下代码
1 | string ip = Configuration["ip"];//部署到不同服务器的时候不能写成127.0.0.1或者0.0.0.0,因为这是让服务消费者调用的地址 |
1 | private static void ConfigurationOverview(ConsulClientConfiguration obj) |
客户端调用
1 | static List<string> Urls = new List<string>(); |
运行即可看到 我们已经成功调用了Consul,也成功的获取到了服务信息。
参考:
https://www.cnblogs.com/shanyou/archive/2015/08/09/4714838.html
https://www.cnblogs.com/kiba/p/11941731.html
https://www.cnblogs.com/yanbigfeg/p/9199590.html
在实际的云服务生产环境中,因为可以按量付费,经常会遇到硬盘不够了需要扩容的情况。
在云平台对对应的硬盘扩容操作
进入主机系统内,查看服务器的磁盘信息fidk -l
之后 找到 硬盘/dev/sda
使用分区工具parted
分区parted /dev/sda
然后使用: print free
查看 Free Space
1 | Model: Msft Virtual Disk (scsi) |
使用mkpart
开始分区mkpart test 186GB 100%
然后看到 /dev/sda3
使用fdisk
调理分区为LVMfdisk /dev/sda
然后依次t(change a partition's system id) 3 l(type L to list all codes) 8e(8e Linux LVM) w
使用pvcreate把/dev/sda3搞成物理卷pvcreate /dev/sda3
划分到 卷组vgextend centos /dev/sda3
划分到逻辑卷lvextend -l +100%FREE /dev/mapper/centos-home
保存此次操作
xfs_growfs /dev/mapper/centos-home
如果你的pv在create的时候没有使用分区是话可以使用 pvresize
调整一个卷组中的物理卷的大小
1 | pvresize /dev/sdc |
然后添加到 lv中
lvextend -l +100%FREE /dev/mapper/testvg-testlv
最后 resize 一下
resize2fs /dev/mapper/testvg-testlv
说明:当有在操作系统时发现磁盘空间不足时,可以通过增加磁盘空间大小来满足,但是以哪种方式来增加可能有不同方法,现在针对操作系统在安装采用LVM方式来动态调整磁盘空间大小,
LVM是逻辑盘卷管理(Logical VolumeManager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和分区之上的一个逻辑层,来提高磁盘分区管理的灵活性。通过LVM系统管理员可以轻松管理磁盘分区,如:将若干个磁盘分区连接为一个整块的卷组(volumegroup),形成一个存储池。管理员可以在卷组上随意创建逻辑卷组(logicalvolumes),并进一步在逻辑卷组上创建文件系统。管理员通过LVM可以方便的调整存储卷组的大小,并且可以对磁盘存储按照组的方式进行命名、管理和分配
Linux的LVM非常强大,可以在生产运行系统上面直接在线扩展硬盘分区,可以把分区umount以后收缩分区大小,还可以在系统运行过程中把一个分区从一块硬盘搬到另一块硬盘上面去等等,简直就像变魔术,而且这一切都可以在一个繁忙运行的系统上面直接操作,不会对你的系统运行产生任何影响,很安全。
LVM使用有局限性。虽然能很方便的扩容和缩容磁盘的空间(扩容磁盘大小,文件不丢失),但是一旦出现问题,数据丢失,想要恢复数据就有点困难!
三步:
1 | [root@localhost ~]# df -h |
以上说明 centos-root 和centos-home 是通过LVM方式来配置的
2. 使用df -T -h
命令查看操作系统的文件类型
1 | [root@localhost ~]# df -T -h |
说明:通过查询发现操作系统的文件格式是:xfs
vgdisplay
:查看卷组名称及卷组使用情况
VG Size –总共的空间大小
lvdisplay
:查看当前逻辑卷的空间状态
现在感觉 /dev/centos/home
的73.99G不够用,想扩容增加10G新插入一块10G的硬盘;
fdisk -l
查看 得知新硬盘是 /dev/sdc
1 | Disk /dev/sdc: 10.7 GB, 10737418240 bytes, 20971520 sectors |
/dev/sdc
fdisk /dev/sdc 然后依次 n p 回车 回车 w
fdisk /dev/sdc 然后依次 t(change a partition’s system id) l(type L to list all codes) 8e(8e Linux LVM) w
1 | Disk /dev/sdc: 10.7 GB, 10737418240 bytes, 20971520 sectors |
root@localhost ~]# pvcreate /dev/sdc1
Physical volume “/dev/sdc1” successfully created.
vgextend centos /dev/sdc1
lvextend -l +100%FREE /dev/mapper/centos-home
xfs_growfs /dev/mapper/centos-home
如果文件系统是xfs格式的,fs文件系统只支持增大分区空间的情况,不支持减小的情况(谨记谨记谨记)
硬要减小的话,只能在减小后将逻辑分区重新通过mkfs.xfs命令重新格式化才能挂载上,这样的话这个逻辑分区上原来的数据就丢失了。记得备份原来数据。
也就是说当执行过 xfs_growfs 之后 是无法在不丢失数据是情况下 执行 lvreduce -L -10G /dev/mapper/centos-home
缩小分区的。
创建分区 #fdisk /dev/sdb
创建物理卷 #pvcreat /dev/sdb1
查看卷组名称及使用情况 #vgdisplay
将物理卷扩展到卷组 #vgextend cl /dev/sdb1 (此处‘cl’是卷组名称)
将卷组中空闲空间扩展到 /home #lvextend -l +100%FREE /dev/mapper/cl-home
刷新文件系统是扩容生效 xfs_growfs /dev/mapper/centos-root
若是ext4文件格式使用扩容生效 #resize2fs /dev/mapper/centos-home
群晖总是在超过60度的时候shutdown 可以参考使用 这篇帖子 来解决
具体步骤
使用ssh到群晖上 打开 /usr/syno/etc.defaults/scemd.xml
文件
查找文本
1 | 找到如下内容的文本 关键字`temperature` 和 `SHUTDOWN` |
把其中的 61 或者 58 的数字 修改成90
保存文件 然后重启就好了