-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
53 lines (53 loc) · 44.9 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[iOS能力探索-自动生成视图唯一标识]]></title>
<url>%2F2018%2F10%2F10%2Fuiview_unique_id%2F</url>
<content type="text"><![CDATA[What我们知道苹果提供了手动给控件添加可访问性(Accessibility)的能力,然而这样做的工作量大且不一定能满足需求,只能另辟蹊径从技术自动化方向去尝试解决这个问题。 Why由于组内有不少技术性项目(自动化测试、自动化埋点等…)都需要有唯一标识的能力,于是有了此次的探索。 How在组内小范围讨论了一番并结合网络检索后,总结出以下2种方案: 视图栈方案: 运行时获得视图栈,动态生成唯一标识。 脚本(配置)方案: 提前生成唯一标识的配置数据,然后在运行时进行绑定。 为了方便理解,接下来会用同一个案例来讲述两个方案的差别如下图所示,有一个继承自UIViewController的类V1,其树形结构是用@property关键字声明的递归属性树(为了方便理解,已经由黑白名单策略过滤了私有变量,无效变量等节点)矩形代表ViewController,圆形代表View,菱形代表Object 视图栈方案先说视图栈方案,目前业内开源库里接受度较高的解决方案是TBUIAutoTest,其原理可以简述为: 如果是类的属性变量,则用属性的变量名作为唯一标识。 如果是局部变量,则用其来源的内容作为唯一标识。 图解如下: 该方案也暴露出以下问题: 被复用的视图D,在被复用的父视图A和父视图B中的变量名都是d1,用该方案则会出现同一个unique_id对应多个视图的情况。虽然可以通过运行时的视图栈index来进行区分,但是会出现另一个问题,就是视图的层级可能发生变化,导致unique_id不稳定。 为了解决以上问题,也引出了接下来要重点说明的配置(脚本)方案。 配置(脚本)方案要优化标识可能一致的问题,可以收敛要处理的类的范围,即只处理ViewController继承类的属性树,这也是该方案的关键点。一般来说ViewController被复用的可能性不高,即使真的复用程度高,也可以配合后端下发唯一标识来解决相对定位的问题。 具体实现步骤如下:1.生成配置数据 获得所有VC // objc_getClassList() 递归遍历VC持有的属性树 // class_copyPropertyList() 保存属性树上每个结点的keypath并生成其唯一标识 // md5(keypath) 2.保存格式化后的数据(json) 格式化保存VC的属性树数据(可以静态写入本地文件或保存在远端等) 123456789101112131415// 格式参考{ PRKHomeViewController : { "dce359c476c4ae262e6f958a3e647c25":"guideView", "f1a282bdbf688604b1dc1f5c94df1ada":"myView", "f958a3e6860f688601dcf1ad62e6f958":"myView.loadingView", ... }, PRKDetailViewController : { "b1dc1f5c94df1ad62e6f958aa3e68606":"navbar", "c4ae262e6f958a3e6860e266f958a3e6":"navbar.titleLbl", ... }, ...} 3.关联配置数据关联数据有两种情况 已知unique_id获取视图对象 因为之前已经生成好配置文件,那我们只需要在运行时索引配置表,通过unique_id找到对应的keypath,再通过KVC机制获取到对应的视图对象。 关键代码如下 1234567891011121314151617181920212223242526272829303132/** @brief 传入unique_id和rootVC对象,获得视图 @param uniqueId 唯一标识 @param rootRef 当前的ViewController @return 对应的视图 */- (id)refForUniqueId:(NSString *)uniqueId inRootRef:(id)rootRef { if (uniqueId.length <= 0) { return nil; } id aObj = [[PRKUniqueIdSession sharedSession].uniqueIdRefCache objectForKey:uniqueId]; if (nil != rootRef && [aObj isKindOfClass:[NSDictionary class]]) { return [(NSDictionary *)aObj objectForKey:[NSString stringWithFormat:@"%p",rootRef]]; } if (nil == aObj && rootRef && uniqueId) { // NOTE: try to find object by KVC NSString *keyPath = [[PRKUniqueIdSession sharedSession] keyPathForUniqueId:uniqueId inRootClass:[rootRef class]]; id ref = nil; @try { ref = [rootRef valueForKeyPath:keyPath]; } @catch (NSException *exception) { } @finally { if (ref) { NSString *uniqueId = [[PRKUniqueIdSession sharedSession] uniqueIdForKeyPath:keyPath inRootClass:[rootRef class]]; [(NSObject *)ref setPrk_sfRootRef:rootRef]; [(NSObject *)ref setPrk_sfUniqueId:uniqueId]; aObj = ref; } } } return aObj;} 已知视图对象获取unique_id 用runtime的提供的相关API找到对象的varName以及对象的ViewController,再通过配置表定位到他的unique_id。 关键代码如下: 12345678910111213141516171819202122232425262728293031// @category: NSObject+uniqueId- (NSString *)prk_sfUniqueId { NSString *result = (NSString *)objc_getAssociatedObject(self, _kNSObject_prk_sfUniqueId); // NOTE: 初始化赋值 if (nil == result && [self isKindOfClass:[UIResponder class]]) { // NOTE: 兼容性逻辑,在此初始化一番 NSString *varName = [(UIResponder *)self prk_findNameWithInstance:(UIResponder *)self]; UIViewController *rootRef = [(UIResponder *)self prk_findViewController]; if (varName.length > 0 && rootRef) { // NOTE:遍历对应rootRef的所有keypath的lastObject对应的ref匹配,匹配则返回对应值 NSDictionary *map = [[PRKUniqueIdSession sharedSession] uniqueIdKeyPathMapInRootClass:[rootRef class]]; if (map.count <= 0) { return result; } NSMutableArray *maybelist = [NSMutableArray arrayWithCapacity:map.allValues.count]; for (NSString *aKeyPath in map.allValues) { if ([aKeyPath hasSuffix:varName]) { [maybelist addObject:[map allKeysForObject:aKeyPath].lastObject]; } } for (NSString *uniqueId in maybelist) { // 该方法已给self赋值unique_id id ref = [PRKUinqueIdKit prk_fetchRefForUniqueId:uniqueId inRootRef:rootRef]; if (ref == self) { return uniqueId; } } } } return result;} 同样我们再图解一番该方案: 用视图的keypath作为唯一标识(为了让unique_id长度一致,对其进行了md5编码)能保证在同一个VC下,被复用的视图的唯一标识不同,解决了视图栈方案的唯一标识重复问题。被复用的视图D,在其父视图A下的唯一标识分别是md5(o1.a1.d1)和md5(o1.a2.d1),在父视图B中的唯一标识是md5(b1.d1) 模块设计图介于尚未获得公司的开源许可,暂放一张模块设计图供大家参考。 TODO最后再说明下目前脚本(配置)方案的局限性:只覆盖了通过@property方式或者iVar方式声明的属性。以下是需要完善的地方及其解决方案的思考: 完善手动赋值情况: 提供生成唯一标识的规则 VC被复用的场景: 可以通过服务器下发配合客户端赋值来解决 列表元素类型(UITableViewCell、UICollectionViewCell): 可以通过服务器下发配合客户端赋值来解决 局部变量: 可以复用TBUIAutoTest的方案临时解决(待完善) Reference 为 UIAutomation 添加自动化测试标签的探索 Macaca UI 自动化利器-为你的应用自动添加控件 ID 探索 Appium]]></content>
<tags>
<tag>iOS</tag>
</tags>
</entry>
<entry>
<title><![CDATA[iOS逆向分析和注入-微信防撤回]]></title>
<url>%2F2018%2F03%2F26%2FiOS%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%92%8C%E6%B3%A8%E5%85%A5-%E5%BE%AE%E4%BF%A1%E9%98%B2%E6%92%A4%E5%9B%9E%2F</url>
<content type="text"><![CDATA[复习iOS逆向知识,以微信消息防撤回为例,一步一步分析调试,到完成插件注入。 环境配置越狱iPhone 5s (iOS 10.1.1) 并安装了以下软件: OpenSSH: 实现在越狱手机上远程进行 ssh 服务,通过 ssh,即可以通过终端连接 iPhone 进行控制。dumpdecrypted: 砸壳工具。Cycript: 脚本语言工具,用于 hook 正在运行的进程,并实时注入代码。debugserver: 用于连接手机进行 lldb 调试的工具。用 Xcode 在手机上进行 app 调试即可在iPhone目录的 /Developer/usr/bin/ 中生成。 苹果电脑 (macOS High Sierra 10.13.3) 并安装了以下软件: frida-ios-dump: 砸壳利器。class_dump: dump 目标对象的 class 信息的工具。Hopper_Disassembler: 静态分析工具。usbmuxd: 端口转发,可以让我们通过 usb 连接手机进行 ssh、lldb 调试等。lldb: 调试神器,用过的都说好 (/Applications/Xcode.app/Contents/Developer/usr/bin/lldb)。theos: 插件编写IDE。 流程概述 砸壳: frida-ios-dump、dumpdecrypted、Clutch 分析调试: 静态分析: class-dump、Hopper Disassembler 动态分析: Cycript、Logify、lldb+debugserver 编写插件并注入: theos 砸壳推荐使用frida-ios-dump,下面会分别以frida-ios-dump和dumpdecrypted为例进行砸壳,实际情况任选一个使用即可。 frida-ios-dump1.获取app信息 frida-ios-dump/dump.py -l # frida-ios-dump/dump.py -l PID Name Identifier ----- -------------- ------------------------------- 92311 微信 com.tencent.xin - App Store com.apple.AppStore - Cydia com.saurik.Cydia - FaceTime com.apple.facetime - Safari com.apple.mobilesafari ... 2.根据app信息进行砸壳 frida-ios-dump/dump.py [bundle id|name] # frida-ios-dump/dump.py com.tencent.xin Start the target app com.tencent.xin Dumping 微信 to /var/folders/7b/c3cyxy3j0t7_tgnt0dh5wc240000gn/T start dump /var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/WeChat WeChat.fid: 100%|█████████████████████████████████████████████████| 71.8M/71.8M [00:06<00:00, 11.1MB/s] start dump /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/Frameworks/WCDB.framework/WCDB WCDB.fid: 100%|███████████████████████████████████████████████████| 2.49M/2.49M [00:00<00:00, 9.10MB/s] start dump /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/Frameworks/MMCommon.framework/MMCommon MMCommon.fid: 100%|█████████████████████████████████████████████████| 979k/979k [00:00<00:00, 7.56MB/s] start dump /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/Frameworks/MultiMedia.framework/MultiMedia MultiMedia.fid: 100%|█████████████████████████████████████████████| 6.61M/6.61M [00:00<00:00, 10.8MB/s] start dump /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/Frameworks/mars.framework/mars mars.fid: 100%|███████████████████████████████████████████████████| 8.49M/8.49M [00:00<00:00, 11.2MB/s] network_setting.html: 139MB [00:25, 5.62MB/s] 0.00B [00:00, ?B/s] Generating "微信.ipa" 砸壳成功后会在当前目录下生成去壳后的安装包微信.ipa。 dumpdecrypted1.获取app安装路径 ps -e | grep /var/ # ps -e | grep /var/ 92817 ?? 0:16.99 /var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/WeChat 92867 ?? 0:00.20 /private/var/containers/Bundle/Application/FD3685C9-80D5-419E-B106-DF466545003E/News.app/PlugIns/NewsNotificationServiceExtension.appex/NewsNotificationServiceExtension 93182 ttys000 0:00.02 grep /var/ 2.根据app安装路径进行砸壳 DYLD_INSERT_LIBRARIES=/path/to/dumpdecrypted.dylib /path/to/app/executablename # DYLD_INSERT_LIBRARIES=/path/to/dumpdecrypted.dylib /var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/WeChat mach-o decryption dumper DISCLAIMER: This tool is only meant for security research purposes, not for application crackers. [+] detected 64bit ARM binary in memory. [+] offset to cryptid found: @0x1000b4cf8(from 0x1000b4000) = cf8 [+] Found encrypted data at address 00004000 of length 59457536 bytes - type 1. [+] Opening /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/WeChat for reading. [+] Reading header [+] Detecting header type [+] Executable is a plain MACH-O image [+] Opening WeChat.decrypted for writing. [+] Copying the not encrypted start of the file [+] Dumping the decrypted data into the file [+] Copying the not encrypted remainder of the file [+] Setting the LC_ENCRYPTION_INFO->cryptid to 0 at offset cf8 [+] Closing original file [+] Closing dump file 成功后会在当前目录下生成WeChat.decrypted,也就是砸壳后的执行文件。 分析调试Cycript (动态分析工具)官网: http://www.cycript.org/ Cycript允许开发人员调试和修改iOS和Mac OS X上运行的应用程序。Cycript是一个理解Objective-C语法的javascript解释器,它能够挂钩正在运行的进程,能够在运行时修改应用的很多东西。 调试命令 cycript [-p <pid|name>]可以先通过 ps -e | grep /var命令找到对应pid # cycript -p WeChat cy# [[[UIWindow keyWindow] rootViewController] _printHierarchy].toString() `<MMTabBarController 0x14606ae00>, state: appeared, view: <UILayoutContainerView 0x145da6420> | <MMUINavigationController 0x146179800>, state: appeared, view: <UILayoutContainerView 0x145d99460> | | <NewMainFrameViewController 0x1460ff600>, state: disappeared, view: <MMUIHookView 0x145d8efa0> not in the window | | <BaseMsgContentViewController 0x146983e00>, state: appeared, view: <UIView 0x145d7d440> | <MMUINavigationController 0x14618b000>, state: disappeared, view: <UILayoutContainerView 0x145d9dda0> not in the window | | <ContactsViewController 0x146191000>, state: disappeared, view: (view not loaded) | <MMUINavigationController 0x14613a800>, state: disappeared, view: <UILayoutContainerView 0x145da0ec0> not in the window | | <FindFriendEntryViewController 0x146859200>, state: disappeared, view: (view not loaded) | <MMUINavigationController 0x1461a4e00>, state: disappeared, view: <UILayoutContainerView 0x145da3950> not in the window | | <MoreViewController 0x146172c00>, state: disappeared, view: (view not loaded)` Logify (静态分析工具)介绍: http://iphonedevwiki.net/index.php/Logify Logify是一种实用工具,可以将类的头文件(.h文件)作为输入,并生成MobileSubstrate文件(.xm文件)。作用:能自动Hook该类所有的方法,并生成打印日志信息代码,方便开发人员看到在使用过程中调用了某些方法。 # logify.pl BaseMsgContentViewController.h > Tweak.xm Logos 语法介绍: http://iphonedevwiki.net/index.php/Logos 可以在MobileSubstrate文件(.xm文件)中使用的语法 Theos-NIC (动态分析工具)介绍: http://iphonedevwiki.net/index.php/NIC Theos NIC templates内置了多种种Theos工程类型的模板。用于编写iOS越狱设备的插件。 创建一个追踪logify的插件工程: # nic.pl NIC 2.0 - New Instance Creator ------------------------------ [1.] iphone/activator_event [2.] iphone/application_modern [3.] iphone/cydget [4.] iphone/flipswitch_switch [5.] iphone/framework [6.] iphone/ios7_notification_center_widget [7.] iphone/library [8.] iphone/notification_center_widget [9.] iphone/preference_bundle_modern [10.] iphone/tool [11.] iphone/tweak [12.] iphone/xpc_service Choose a Template (required): 11 Project Name (required): TWeak-Logify-WX Package Name [com.yourcompany.tweak-logify-wx]: cn.theos.tweak.wx.logify Author/Maintainer Name [dabing]: author name [iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]: com.tencent.xin [iphone/tweak] List of applications to terminate upon installation (space-separated, '-' for none) [SpringBoard]: Instantiating iphone/tweak in tweaklogifywx/... Done. 工程文件结构如下: # tree . └── tweaklogifywx ├── Makefile ├── TWeakLogifyWX.plist ├── Tweak.xm └── control 将Logify生成的Tweak.xm覆盖掉工程中的Tweak.xm用文本编辑器打开Makefile文件,在文件的开头增加iOS设备的ip地址和ssh端口等信息: THEOS_DEVICE_IP = localhost THEOS_DEVICE_PORT = 2333 ARCHS = arm64 TRAGET = iphone:latest:9.0 include $(THEOS)/makefiles/common.mk TWEAK_NAME = TWeakLogifyWX TWeakLogifyWX_FILES = Tweak.xm logifyWX_FRAMEWORKS = UIKit Foundation CoreGraphics logifyWX_CFLAGS = -fobjc-arc include $(THEOS_MAKE_PATH)/tweak.mk after-install:: install.exec "killall -9 SpringBoard" 编译打包安装: # make package install > Making all for tweak TWeakLogifyWX… ==> Preprocessing Tweak.xm… ==> Compiling Tweak.xm (arm64)… ==> Linking tweak TWeakLogifyWX (arm64)… clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of iOS 7 [-Wdeprecated] ==> Generating debug symbols for TWeakLogifyWX (arm64)… warning: no debug symbols in executable (-arch arm64) ==> Merging tweak TWeakLogifyWX… ==> Signing TWeakLogifyWX… > Making stage for tweak TWeakLogifyWX… dm.pl: building package `cn.theos.tweak.wx.logify:iphoneos-arm' in `./packages/cn.theos.tweak.wx.logify_0.0.1-1+debug_iphoneos-arm.deb' ==> Installing… Selecting previously unselected package cn.theos.tweak.wx.logify. (Reading database ... 2279 files and directories currently installed.) Preparing to unpack /tmp/_theos_install.deb ... Unpacking cn.theos.tweak.wx.logify (0.0.1-1+debug) ... Setting up cn.theos.tweak.wx.logify (0.0.1-1+debug) ... install.exec "killall -9 SpringBoard" 注意:一般该Tweak.xm仍然无法执行,需要进行修改:去掉 .cxx_destruct 方法将 HBLogDebug 改为 NSLog去掉所有的 weak 属性将头文件(.h文件)中的@class和@protocol声明都拷贝至Tweak.xm (或去掉所有delegate并将所有参数对象类型改为id)。 安装成功后会在设备中新增以下两个文件: /Library/MobileSubstrate/DynamicLibraries/TWeakLogifyWX.dylib /Library/MobileSubstrate/DynamicLibraries/TWeakLogifyWX.plist 打开Cydia-已安装可以看到插件已经安装成功: idevicesyslog (iOS日志查看工具)介绍: https://github.com/libimobiledevice/libimobiledevice 是libimobiledevice下的一个子工具,可以实时追踪iOS设备日志。 # idevicesyslog | grep "BaseMsgContentViewController" 重新运行app,执行收到消息和撤回消息的case,可以分别获取两份log: 接收消息log 撤回消息log 整理后log对比可以发现可疑方法调用-[BaseMsgContentViewController OnMsgRevoked:n64MsgId:] class-dump (静态分析工具)介绍: http://stevenygard.com/projects/class-dump/ 这是一个检查存储在Mach-O文件Objective-C运行时信息的命令行实用工具。能生成classes、categories、protocols定义的头文件(.h文件)。(与otool -ov命令获取的信息类似,但可读性更高) # class-dump -HA WeChat -o ./Headers 获得头文件以及方法的IMP address 例如:-[BaseMsgContentViewController OnMsgRevoked:n64MsgId:] // IMP=0x0000000102129454 Hopper Disassembler (分析工具)介绍: https://www.hopperapp.com 是一款32位和64位的二进制反汇编器,反编译和调试。可以使用此工具拆开你想要的任何二进制。 使用方法很简单:将二进制文件拖入软件中,等待处理完成即可。(完整解析微信app需要很长一段时间,可以前置该流程进行解析处理) lldb+debugserver (动态分析) 1.打开微信后,在连接至设备的控制台中键入debugserver *:1234 -a "WeChat"启动debugserver。2.从控制台打开新窗口,键入lldb进入调试,再键入process connect connect://192.168.1.19:1234连接1234端口。 (此处连接上需要一点时间,可以上个厕所,连接上后键入c(continue)后app就可以正常运行了)连接成功后lldb窗口会出现以下内容: (lldb) process connect connect://192.168.1.19:1234 Process 73244 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP frame #0: 0x00000001900f5164 libsystem_kernel.dylib`__fcntl + 8 libsystem_kernel.dylib`__fcntl: -> 0x1900f5164 <+8>: b.lo 0x1900f517c ; <+32> 0x1900f5168 <+12>: stp x29, x30, [sp, #-0x10]! 0x1900f516c <+16>: mov x29, sp 0x1900f5170 <+20>: bl 0x1900d9e8c ; cerror Target 0: (WeChat) stopped. (lldb) c Process 73244 resuming 获取aslr的offset。(每次启动都不同)其中第一列[X]是image的序号,不用管;第二列是aslr的offset(也就是对应image的虚拟内存slide);第三列是image的全路径和slide之后的基地址,也不用管~所以第二列就是我们需要的信息。 (lldb) image list -o -f [ 0] 0x0000000000048000 /var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/WeChat(0x0000000100048000) [ 1] 0x0000000104a20000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/usr/lib/dyld [ 2] 0x0000000104970000 /Library/MobileSubstrate/MobileSubstrate.dylib(0x0000000104970000) [ 3] 0x000000000fab4000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/System/Library/Frameworks/CallKit.framework/CallKit [ 4] 0x000000000fab4000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/System/Library/Frameworks/Accelerate.framework/Accelerate [ 5] 0x000000000fab4000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/System/Library/Frameworks/Intents.framework/Intents [ 6] 0x000000000fab4000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/usr/lib/libbz2.1.0.dylib [ 7] 0x0000000104aa4000 /private/var/containers/Bundle/Application/FC7574FD-C99D-49DE-8130-AF824051424A/WeChat.app/Frameworks/WCDB.framework/WCDB(0x0000000104aa4000) [ 8] 0x000000000fab4000 /Users/passerbycrk/Library/Developer/Xcode/iOS DeviceSupport/10.1.1 (14B100)/Symbols/System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore ... 得到aslr的offset:0x0000000000048000 (不同的发布版本偏移量不一定相同)再根据class-dump获得的头文件,找到对应的方法,在后面可以看到IMP的offset。-[BaseMsgContentViewController OnMsgRevoked:n64MsgId:] // IMP=0x0000000102129454通过br命令设置断点(aslr_offset + IMP_offset) (lldb) br s -a '0x0000000000048000+0x0000000102129454' Breakpoint 1: where = WeChat`ClearDataItem::compareTime(std::__1::shared_ptr<ClearDataItem> const&, std::__1::shared_ptr<ClearDataItem> const&) + 4373492, address = 0x0000000102171454 进入断点 Process 73244 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x0000000102171454 WeChat`ClearDataItem::compareTime(std::__1::shared_ptr<ClearDataItem> const&, std::__1::shared_ptr<ClearDataItem> const&) + 4373492 WeChat`ClearDataItem::compareTime: -> 0x102171454 <+4373492>: stp x24, x23, [sp, #-0x40]! 0x102171458 <+4373496>: stp x22, x21, [sp, #0x10] 0x10217145c <+4373500>: stp x20, x19, [sp, #0x20] 0x102171460 <+4373504>: stp x29, x30, [sp, #0x30] Target 0: (WeChat) stopped. (lldb) bt * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 * frame #0: 0x0000000102171454 WeChat`ClearDataItem::compareTime(std::__1::shared_ptr<ClearDataItem> const&, std::__1::shared_ptr<ClearDataItem> const&) + 4373492 frame #1: 0x0000000104d5b980 MMCommon`_callExtension + 480 frame #2: 0x0000000102ccfaac WeChat`ClearDataItem::compareTime(std::__1::shared_ptr<ClearDataItem> const&, std::__1::shared_ptr<ClearDataItem> const&) + 16294476 frame #3: 0x0000000102cda958 WeChat`ClearDataItem::compareTime(std::__1::shared_ptr<ClearDataItem> const&, std::__1::shared_ptr<ClearDataItem> const&) + 16339192 frame #4: 0x0000000102cdb60c WeChat`ClearDataItem::compareTime(std::__1::shared_ptr<ClearDataItem> const&, std::__1::shared_ptr<ClearDataItem> const&) + 16342444 frame #5: 0x0000000104d5b980 MMCommon`_callExtension + 480 frame #6: 0x0000000102f89414 WeChat`ClearSessionItem::compareVideo(std::__1::shared_ptr<ClearSessionItem> const&, std::__1::shared_ptr<ClearSessionItem> const&) + 1516048 ... python+Hopper Disassembler 获取调用栈 >>> hex(0x0000000102171454-0x0000000000048000) '0x102129454' // -[BaseMsgContentViewController OnMsgRevoked:n64MsgId:] >>> hex(0x0000000102ccfaac-0x0000000000048000) '0x102c87aac' // -[CMessageMgr onRevokeMsg:] 使用Hopper Disassembler可以定位调用方法名,此处我们发现可疑函数调用-[CMessageMgr onRevokeMsg:] 编写插件并注入创建插件工程 # nic.pl NIC 2.0 - New Instance Creator ------------------------------ [1.] iphone/activator_event [2.] iphone/application_modern [3.] iphone/cydget [4.] iphone/flipswitch_switch [5.] iphone/framework [6.] iphone/ios7_notification_center_widget [7.] iphone/library [8.] iphone/notification_center_widget [9.] iphone/preference_bundle_modern [10.] iphone/tool [11.] iphone/tweak [12.] iphone/xpc_service Choose a Template (required): 11 Project Name (required): Tweak-crack-WX Package Name [com.yourcompany.tweak-crack-wx]: Author/Maintainer Name [dabing]: [iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]: com.tencent.xin [iphone/tweak] List of applications to terminate upon installation (space-separated, '-' for none) [SpringBoard]: Instantiating iphone/tweak in tweakcrackwx/... Done. Tweak.xm %hook CMessageMgr - (void)onRevokeMsg:(id)arg1 { // do nothing } %end 安装 # make package install > Making all for tweak TweakcrackWX… make[2]: Nothing to be done for `internal-library-compile'. > Making stage for tweak TweakcrackWX… dm.pl: building package `com.yourcompany.tweak-crack-wx:iphoneos-arm' in `./packages/com.yourcompany.tweak-crack-wx_0.0.1-2+debug_iphoneos-arm.deb' ==> Installing… Selecting previously unselected package com.yourcompany.tweak-crack-wx. (Reading database ... 2277 files and directories currently installed.) Preparing to unpack /tmp/_theos_install.deb ... Unpacking com.yourcompany.tweak-crack-wx (0.0.1-2+debug) ... Setting up com.yourcompany.tweak-crack-wx (0.0.1-2+debug) ... install.exec "killall -9 SpringBoard" 打开Cydia-已安装可以看到插件已经安装成功: 接下来重新运行微信,试试消息撤回的case,发现消息撤回已经被阻止了,任务完成~(文章特意选了个软柿子案例,实际情况可能不会这么容易找到关键函数,需要反复调试验证) 源码GitHub/passerbycrk/PRK_iOSRE/Demo/WeChat_MsgRevoke_theos 参考iOSREfridafrida-ios-dumpiphonedevwikiiOS SecurityiOS Reverse Debug Cheatsheet一步一步用debugserver + lldb代替gdb进行动态调试移动App入侵与逆向破解技术-iOS篇]]></content>
<tags>
<tag>Tutorial</tag>
<tag>iOSRE</tag>
</tags>
</entry>
<entry>
<title><![CDATA[mac下配置wine环境]]></title>
<url>%2F2017%2F07%2F04%2Finstall_wine%2F</url>
<content type="text"><![CDATA[转自:在mac下配置wine环境——自己wine一个小游戏 当我们想要在 mac 上运行 labview 等 windows 下的大型软件时,使用 PD 等虚拟机可以很好的解决需求;然而如果我们只想玩些同人小游戏什么的,再开一个操作系统就觉得有点累赘了,这时我们可以选择wine,更加轻量的执行 windows 应用。 wine 的另一个好处时可以将 windows 应用打包成 APP,这样就可以直接拷贝给别人玩儿了! 下面是踩过很多坑后总结出来的比较方便的在 mac 上配置 wine 的流程。 准备工作安装 Xcode 从 Mac Apple Store 安装 安装 XQuzrtz 在这里下载安装。 安装 homebrew $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 温馨提示:homebrew 的源可选择使用清华大学TUNA镜像源提升速度 安装 wine安装 wine $ brew install wine 安装 winetricks $ brew install winetricks 运行应用程序现在我们已经可以执行 windows 应用程序啦。终端下输入 $ wine setup.exe 就可以执行 setup.exe。 执行 $ msiexec /i setup.msi 可以执行msi格式的安装程序。 安装常用库虽然理论上我们已经可以跑 windows 应用程序了,但是游戏还不能玩哦。因为很多依赖都没有安装,比如 .NET Framework,比如 DirectX9,比如 VCRUNTIME 等等。这时候我们需要 winetricks 来帮助我们安装库。 $ winetricks dotnet35 d3dx9 xna31 已有库的列表可通过 winetricks list 来查询。加参数 -q 可以静默安装。 不过 winetricks 这东西内置了复杂的 conflict 系统,有冲突时就不给安装。。比如先装完 .net 2.0再装 .net 3.5会报错。只能选择直接装 .net 3.5。 wine 有一份应用程序的兼容性文档,在装软件时可以先来查阅一下,会有兼容性评级和一些安装说明,十分好用! 打包简易的 wineskin 小教程! 下载 wineskin 安装engine和wrapper。不过 wineskin 自带下载没速度,还是到mediafire下载吧。下载时注意版本要和wine对应哦! 都安装好engine和wrapper后,点击 Create new blank wrapper,输入文件名创建新包,弹出的提示都选 cancel,先不安装。 在wrapper里,运行 wineskin.app 选择 Advanced, tool 里有 winetricks 来装常用库,Configuration 中的 Windows EXE 中输入的应用程序路径就是最终打包成品 APP 双击运行的应用。如果有安装程序的话,路径填进去,选择 Test Run 跑一下。最后再把启动 exe 填进去。 PS. 如果之前在 wine 中装过程序了,直接把~/.wine下的 driver_c文件夹彻底拷贝到wrapper/Content/Resources下,然后指定下 exe 路径就可以直接拿来用。 wine 坑多坑大,很多程序不能完美运行,报错是免不了的,不要慌,google 多查一查!解决不了的,还是打开 PD 吧。 测试123运行环境macOS Sierra10.12.5 (16F73) 测试运行IDAPro v6.8绿色版成功 下载windows版IDA]]></content>
<tags>
<tag>Mac</tag>
<tag>Install</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Xcode Framework制作流程详情整理]]></title>
<url>%2F2017%2F06%2F06%2Fxcode_build_framework%2F</url>
<content type="text"><![CDATA[转自: Xcode 7 Framework制作流程详情整理 1、新建iOS->Framework & Library->Cocoa Touch Framework 2、选择next进入下一步 3、在PROJECT->Deployment Target->iOS Deployment Target选择你需要支持的最低系统。 同样的操作在TARGETS中,Deployment Info->Deployment Target 4、由于我的framework需要支持iOS7,所以在第2、3步中进行了相应的设置。Build时会发现有️ld: warning: embedded dylibs/frameworks only run on iOS 8 or later警告,这是因为工程默认编译设置的是Dynamic Framework。这种编译只有在iOS8以后才能使用。 5、针对第4步中所出现的问题,根据需求我的工程不需要使用动态framework,以使用其动态更新的功能。动态库可以分开发布,在运行时查找并存入内存,但苹果只允许他自己用,到iOS8以后才开放给开发者。因此,我需要将Dynamic Framework更换为Static Library静态模式。设置路径为Build Settings->Linking->Mach-O Type->Static Library 6、这里要注意,在编译时,不要将图片文件放在工程里面,否则编译后framework中会出现大量的零散图片文件在里面。这时需要将图片等资源放在.bundle文件中。 7、这样打包的framework依然有问题,如果你用了Category,别人在用你的framework时会发生崩溃。这时别人在引用时需要在工程中other linker flags中添加-objC如果依然有问题,再添加-all_load。 8、终于编译成功,但发现很多关于符号表的警告,这时需要将Generate Debug Symbols设置为NO即可关闭符号表警告。 9、但是我需要支持bitcode,以上设置后并不能使framework支持bitcode,因此还需要进行额外的设置一个命令让其支持bit code。在TAGETS的Build setting中搜索Other C Flags,添加命令“-fembed-bitcode”。同样的设置在PROJECT中。如果不进行以上操作。别人在集成你的framework时可以编译,亦可以真机测试。唯独在打包时会发出警告并打包失败。警告为framework不支持bitcode! 10、无论SDK还是Framework都需要暴露公共的头文件以供使用者读取和。在TARGETS->Build Phases->Headers里面,有三种类别。Public(公共的),这里存放供其他人查看的header。Private(私有的)这里存放私有的Header,以上两个Headers存放位置都会暴露出来,所有人可以查看。有些Header是不想给别人看到的。这种header放在第三个类Project中。 11、打包。Edit Scheme->Build Configuration->选为Release然后Run. 直接导出方法: 1.添加 target --> other -->aggregate 2.在新建的Target里边添加一个脚本:Build Phases -->new Run Script Phase 3.填入下面脚本到 Run Script 查询framework支持架构:打开终端 lipo -info +路径 # begin ============================================= # Sets the target folders and the final framework product. # 如果工程名称和Framework的Target名称不一样的话,要自定义FMKNAME # 例如: FMK_NAME = "MyFramework" FMK_NAME=${PROJECT_NAME} # Install dir will be the final output to the framework. # The following line create it in the root folder of the current project. INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework # Working dir will be deleted after the framework creation. WRK_DIR=build DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework # -configuration ${CONFIGURATION} # Clean and Building both architectures. xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos -arch armv7 -arch armv7s -arch arm64 clean build xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator -arch x86_64 clean build # Cleaning the oldest. if [ -d "${INSTALL_DIR}" ] then rm -rf "${INSTALL_DIR}" fi mkdir -p "${INSTALL_DIR}" cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/" # Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product. lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}" rm -r "${WRK_DIR}" open "${SRCROOT}/Products/" # end =============================================== PS:脚本需要跑一遍真机,再跑一遍模拟器才会build success]]></content>
<tags>
<tag>Tutorial</tag>
</tags>
</entry>
<entry>
<title><![CDATA[多米尼克体系-编码表]]></title>
<url>%2F2017%2F03%2F29%2Fmemory_encoding%2F</url>
<content type="text"><![CDATA[声母编码声母正好20个,可以规划为2x10赋予10个数两组编码bpmf-dtnl-gkh-jqx-zcsr-yw特殊:aoe iuv 都当做是0 0 1 2 3 4 5 6 7 8 9 d y z m s w l q b j c t r k p h n f x g 0~9 编码 数字 声母 联想 0 d 蛋/洞/鼎/盾 1 y 雁/蚁/鱼/鹰 2 z 嘴/粽/枣/砖 3 m 矛/帽/马/锚 4 s 伞/锁/扇/梳 5 w 碗/蛙/网/瓦 6 l 锣/龙/狼/螺 7 q 球/桥/枪/钳 8 b 豹/靶/蚌/笔 9 j 酒/剑/剪/锯 00~99 编码 数字 声母 生物 行为 00 dd-dc-cd-cc 大盗 蒙面持短刀 01 dy-dt-cy-ct 导游 持小喇叭举小旗 02 dz-dr-cz-cr 队长/DZ 臂章五道杠 03 dm-dk-cm-ck 达摩 头顶有三排戒疤 04 ds-dp-cs-cp 袋鼠 肚子上有个口袋 05 dw-dh-cw-ch 典韦 持双戟 06 dl-dn-cl-cn 大佬 (北野武)戴墨镜+叼雪茄 07 dq-df-cq-cf 大乔 持灯笼守望着天空大海和你的回忆 08 db-dx-cb-cx 大白/大饼 碳纤维充气白外套/写代码 09 dj-dg-cj-cg 妲己 漏出狐狸尾巴 10 yd-yc-td-tc 玉帝 头戴皇冠 11 yy-yt-ty-tt 爷爷 带着老花镜 12 yz-yr-tz-tr 鸭子 扁扁的嘴巴+展开的鸭掌 13 ym-yk-tm-tk 姚明/樱木 红色的头发+灌篮 14 ys-yp-ts-tp 耶稣 绑在十字架上 15 yw-yh-tw-th 叶问 打咏春拳 16 yl-yn-tl-tn 月老 牵红线 17 yq-yf-tq-tf 月骑 骑黑豹+持月刃 18 yb-yx-tb-tx 伊布 从精灵球里出来 19 yj-yg-tj-tg 杨戬 持三叉戟+三眼 20 zd-zc-rd-rc 周董 “哎呦不错哟” 21 zy-zt-ry-rt 赵云 持龙胆枪和青釭剑 22 zz-zr-rz-rr 庄周/蜘蛛 骑鲲/吐丝结网 23 zm-zk-rm-rk 掌门 《九阴真经》 24 zs-zp-rs-rp 宙斯 手持雷霆和宙斯之盾 25 zw-zh-rw-rh 张伟/纣王 吃小龙虾过敏/好酒淫乐 26 zl-zn-rl-rn 蟑螂 头上有两黑色大触须 27 zq-zf-rq-rf 朱雀 全身火焰献祭 28 zb-zx-rb-rx 张苞 继承丈八蛇矛 29 zj-zg-rj-rg 张角 头戴黄巾可引雷 30 md-mc-kd-kc 马东/麦兜 奇葩说议长/猪鼻子端着一碗鱼丸粗面 31 my-mt-ky-kt 马云/蚂蚁 淘宝董事长/成群结队搬运糖 32 mz-mr-kz-kr 蚂蚱 啃食庄稼 33 mm-mk-km-kk 孟母/妈妈 收拾行李准备搬家/围裙+颠勺 34 ms-mp-ks-kp 牧师 一身黑袍持法杖施法 35 mw-mh-kw-kh 猫王 飞机头 36 ml-mn-kl-kn 马良 用神笔画龙点睛 37 mq-mf-kq-kf 米奇 拿着彩色气球 38 mb-mx-kb-kx 麦霸 在KTV抢麦唱歌 39 mj-mg-kj-kg 母鸡 下鸡蛋 40 sd-sc-pd-pc 上帝 头带光圈 41 sy-st-py-pt 鲨鱼 有垂直的背鳍 42 sz-sr-pz-pr 狮子 脸边缘长满鬃毛 43 sm-sk-pm-pk 水母 透明发光 44 ss-sp-ps-pp 松鼠 吃松子 45 sw-sh-pw-ph 孙武/沙王 著《孙子兵法》/摇尾释放地震波 46 sl-sn-pl-pn 神乐 拿着雨伞枪,吃着醋昆布 47 sq-sf-pq-pf 圣骑 带有圣盾 48 sb-sx-pb-px 孙膑 著《孙膑兵法》 49 sj-sg-pj-pg 沙加 穿处女座黄金圣衣 50 wd-wc-hd-hc 卧底 黑色皮衣+手枪:我想做个好人 51 wy-wt-hy-ht 乌鸦 往瓶子里填石子 52 wz-wr-hz-hr 蚊子 长长尖尖的嘴能戳破皮肤 53 wm-wk-hm-hk 无名/网民 万剑归宗/用键盘输出 54 ws-wp-hs-hp 武松 用碗喝酒+打虎 55 ww-wh-hw-hh 王维 画中有诗 56 wl-wn-hl-hn 卧龙 羽扇纶巾 57 wq-wf-hq-hf 雾切 猎鹿帽+披风=超高级侦探 58 wb-wx-hb-hx 王八 藏在龟壳里 59 wj-wg-hj-hg 武警/吴京 防弹衣+防弹头盔+步枪 60 ld-lc-nd-nc 林丹 持羽毛球拍 61 ly-lt-ny-nt 柳岩/老鹰 S曲线身材/大翅膀盘旋在天空 62 lz-lr-nz-nr 老子/驴子 著《道德经》/拉磨 63 lm-lk-nm-nk 狸猫 翻找垃圾桶 64 ls-lp-ns-np 老师/老鼠 在讲台用教鞭敲黑板/偷吃老鼠夹上的奶酪 65 lw-lh-nw-nh 鹿丸 使用影子模仿术 66 ll-ln-nl-nn 李雷/萝莉 how r u / 穿萝莉装 67 lq-lf-nq-nf 刘谦 白手套+魔术:见证奇迹 68 lb-lx-nb-nx 刘备 持雌雄双股剑 69 lj-lg-nj-ng 李靖 手里托塔 70 qd-qc-fd-fc 乔丹 代言篮球鞋 71 qy-qt-fy-ft 屈原/琼瑶/蚯蚓 吃粽子/钻地松土 72 qz-qr-fz-fr 酋长 黝黑的皮肤脸上涂着迷彩,举行篝火晚会 73 qm-qk-fm-fk 球迷 脸上印着国旗并大声呐喊 74 qs-qp-fs-fp 琴师 弹奏古琴 75 qw-qh-fw-fh 青蛙 坐在荷花上吐舌头吃蚊子 76 ql-qn-fl-fn 麒麟 送子 77 qq-qf-fq-ff QQ 红色大围脖 78 qb-qx-fb-fx 乔巴/丘比 鹿角上带着红色帽子/签订契约 79 qj-qg-fj-fg 巧匠? (鲁班)手持锯子和小锤捣鼓木材 80 bd-bc-xd-xc 笨蛋 试卷:0分+药不能停 81 by-bt-xy-xt 贝爷 吃虫子,嘎嘣脆 82 bz-br-xz-xr 包拯 脸黑+月亮印 83 bm-bk-xm-xk 斑马 黑白条纹皮肤 84 bs-bp-xs-xp 博士/白叟 带着护目镜做试验/头发斑白+独钓于江边 85 bw-bh-xw-xh 霸王? 力拔山,气盖世 86 bl-bn-xl-xn 伯乐/冰龙 识好马/巨大寒冰双翼+喷吐寒气 87 bq-bf-xq-xf 扁鹊 切脉诊病 88 bb-bx-xb-xx 宝宝 叼着奶嘴 89 bj-bg-xj-xg 八戒 拿着钉耙挥舞 90 jd-jc-gd-gc 角都/间谍 有多个心脏/窃取文件机密 91 jy-jt-gy-gt 鲸鱼 头顶喷水柱 92 jz-jr-gz-gr 精子/军长 数量繁多+白色小尾巴/衣带肩章 93 jm-jk-gm-gk 巨魔 投射火焰长矛 94 js-jp-gs-gp 剑圣 持剑使出剑刃风暴 95 jw-jh-gw-gh 九尾 有九条尾巴 96 jl-jn-gl-gn 蛟龙/精灵 腾云驾雾 97 jq-jf-gq-gf 警犬 安检闻行李 98 jb-jx-gb-gx 街霸/嘉宾 释放冲击波 99 jj-jg-gj-gg 交警 在交警亭里指挥交通+开罚单 PS:可以根据自己熟悉的事物来编码,以上只是为自己整理的编码表。 参考 多米尼克体系-中文记忆法]]></content>
<tags>
<tag>Memory</tag>
</tags>
</entry>
<entry>
<title><![CDATA[使用github+jekyll搭建博客]]></title>
<url>%2F2016%2F09%2F23%2Fsetup_blog%2F</url>
<content type="text"><![CDATA[2017-07-06 更新改用Hexo建站 参考: hexo你的博客 手把手教你使用Hexo + Github Pages搭建个人独立博客 在GitHub上创建repository搭建要用github pages,首先要在github中建立一个基于你的用户名的repository: 比如说我,就要建立名为passerbycrk.github.io的repo。在以前的github版本中还需要在后台开启pages的功能,现在系统检测到这样的repo名称之后,会在setting中自动开启GitHub Pages的功能,如下图:这样之后你就可以把这个repo克隆到本地随意进行修改了,在这个里面上传的网页就是你的网站的内容了,可以上传一个index.html试一试,这就是你的网站主页了。关于GiuHub的使用,可以看几个比较好的入门教程:GiuHub使用教程传送门 集成本地部署环境之后我们就要在本地部署jekyll,jekyll的原理很简单。这是一个已经合成好的静态html网站结构,你用这个结构在username,github.io文件夹里面粘帖好所有文件。再把更新完的本地repo推送到GitHub的master branch里面,你的网站就更新建设完毕了。首先你需要ruby来使用本地jekyll。Mac和Linux可以用Terminal配合yum或者brew这样的包管理器很方便的安装ruby。Windows下更是方便,可以直接中集成好的Ruby installer来进行安装,文章里的就是传送门。安装完ruby,之后就是要安装RubyGems,gem是一个ruby的包管理系统,可以用gem很方便的在本地安装ruby应用。安装方法如下: 在RubyGems官网上下载压缩包,解压到你的本地。 在Terminal中输入以下代码: $ cd your path to RubyGems // RubyGems解压的位置 $ ruby setup.rb 安装jekyll有了gem之后安装jekyll就很容易了,其实用过nodejs和npm的同学应该很熟悉这样的包安装,真是这个世界手残脑残们的救星。。。。。(楼主不自觉的摸了摸自己快残了的手) 接下来在Terminal中输入安装jekyll代码: $ gem install jekyll 等待安装完成。 文件目录结构好了,现在你的电脑已经准备完毕了。如果你是想自己捣鼓,可以根据这样的目录结构在你的{username}.github.io文件夹下建立以下目录结构: ├── _config.yml ├── _drafts | ├── begin-with-the-crazy-ideas.textile | └── on-simplicity-in-technology.markdown ├── _includes | ├── footer.html | └── header.html ├── _layouts | ├── default.html | └── post.html ├── _posts | ├── 2007-10-29-why-every-programmer-should-play-nethack.textile | └── 2009-04-26-barcamp-boston-4-roundup.textile ├── _site └── index.html 选择模板如果你只是个普通用户,只是想要一个模板然后开始写自己的博客。那就很容易了,有几个可以简单开始的模板。 极简风格的模板:https://github.com/poole/poole jekyll的模板网站:http://jekyllthemes.org/ 本地部署发布下载完了模板,可以吧里面的内容解压到你自己的网站目录底下。这时候你可以测试一下: $ cd your website path // cd到你的网站目录下 $ jekyll serve 接下来部署的博客会运行在 http://localhost:4000/ 在浏览器中输入以上地址回车后就可以看到你用模板搭建的网站了。 配置这时候可以看一下jekyll的设置,让你把模板变成你自己个性化的内容。在网站根目录下面找到 _config.yml,这里会有几个比较关键的设置:里面的permalink 就是你博客文章的目录结构,可以用pretty来简单的设置成日期+文章标题.html,也可以用自己喜欢的结构来设置。记得把encoding 设置成utf-8,这样有利于中英文双语的写作和阅读。 发布内容到这里你就可以开始写博客了,所有的文章直接放在_posts文件夹下面,格式就是我们之前提到的markdown文件,默认的格式是.md和.markdown文件。每篇文章的开始处需要使用yml格式来写明这篇文章的简单介绍,格式如下: --- layout: post title: "文章标题" subtitle: "文章副标题" date: 2016-09-23 12:00:00+00:00 author: "作者昵称" --- layout就是post,让jekyll知道你这是一篇post,很直观。需要注意的是里面的date,必须按照yml的语法来写,否则就会出现编译错误。可以只用YYYY-MM-DD来显示日期,也可以像我一样在后面加上 HH:MM:SS+00:00 来表示更具体的时间。 结束到此为止可以开始尽情的写博客了,用GitHub软件同步到你的repository里面,网站上面就可以进行正常的显示了。 参考 在github pages网站下用jekyll制作博客教程 Hux blog 模板 leonids 模板]]></content>
<tags>
<tag>Tutorial</tag>
</tags>
</entry>
</search>