市场情绪指标
可以量化一下,有时间考虑程序实现。
- 涨/跌停板数
- 涨停封版成功率
- 涨跌股票比率
- 大盘成交量额
- 融资余额情况
- 北向资金净流入 (参考)
可以量化一下,有时间考虑程序实现。
总的来说定投属于策略型的投资方法,其实并不知道底和顶在哪里,通过拉长时间来降低持仓成本,因此定投成功的关键在于你的成本是否可以随着时间而降下来。从这点也可以分析出在底部区域定投比在顶部区域定投要好得多,这也就是第一条。
定投策略对历史的估值情况有很强的依赖,属于基于历史数据的统计分析,但是每一次的情况都不同,没有人可以保证历史一定会重演。定投也不是价值投资,没有护城河,只是相信均值回归,这是第二条。
巴菲特非常推荐标普500指数 (S&P 500) 定投,指数基金最牛的地方是股票会定期调整,把好的股票加入进来,差的淘汰出去,相当于有人帮你选股了,另外足够分散,发生系统性风险的概率大幅降低。周期性行业则是爆发性很强,三年不开张,开张吃三年,容易在底部积累大量筹码,作为一个长期投资策略非常合适。
Fedora 36 正式版已经释出一段时间了,根据我的经验开始的一周都会有 bug,一般等一段时间再升级会更平滑一些。然而,老革命又遇上了新问题,显示出问题了启动不起来。我已经很久没有遇上显示驱动问题了,我在很久以前就禁用了开源驱动 nouveau
,一直都用得很好。
修改 /etc/default/grub 文件,在 GRUB_CMDLINE_LINUX
添加下面参数
1 | GRUB_CMDLINE_LINUX="... rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1" |
重新生成 grub 文件, sudo grub2-mkconfig -o /boot/grub2/grub.cfg
,但是在升级 Fedora 36 后似乎没有起作用。诡异的是 Fedora 35 的内核却可以正常工作,首先怀疑的是 nvidia 驱动可能没有安装对。执行下面命令行
1 | sudo dnf reinstall xorg-x11-drv-nvidia akmod-nvidia kmod-nvidia.x86_64 |
可惜没有解决问题,上网找资料看看 Fedora 36 有没什么特殊的地方。安装 Nvidia 驱动网上有这篇文章说的详细
https://www.linuxcapable.com/how-to-install-nvidia-drivers-on-fedora-36-linux/
仔细拜读了一下,还是没有发现啥问题,驱动也重新安装了啊,开始怀疑是新版 Nvidia 驱动的问题
sudo dnf search xorg-x11-drv-nvidia
可以查看所有的驱动,xorg-x11-drv-nvidia-340xx
xorg-x11-drv-nvidia-340xx
xorg-x11-drv-nvidia-340xx
不知道到底需要安装哪个版本的驱动。😭
1 | xorg-x11-drv-nvidia.x86_64 : NVIDIA's proprietary display driver for NVIDIA graphic cards |
可是仔细一琢磨, Fedora 35 Nvidia 驱动不是工作正常吗,可以上去看看用的是哪个版本的驱动,执行命令 nvidia-settings
,在 System Information 中发现使用的就是最新版本的驱动 510.68.02,看样子最新版本的驱动也没有问题,一下陷入了困境。😰
没啥好办法,还是 Google 搜索一下,结果发现了一个链接在讨论这个问题,和我遇上的现象一样,作者最终解决了问题
Fedora Linux kernel update breaks NVIDIA driver
原来是旧版的驱动没有卸载干净,参考 https://rpmfusion.org/Howto/NVIDIA#Uninstall_the_NVIDIA_driver
驱动卸载 Nvidia 驱动需要使用命令 dnf remove xorg-x11-drv-nvidia\*
按照下面的命令操作了一遍,重启系统,熟悉的登录界面终于又出现了。😄
1 | sudo dnf remove xorg-x11-drv-nouveau |
Protocol buffers are Google’s language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.
这段是 Google 官方网站给出的介绍,protobuf 可以自动化生成代码,用于读入或者写入结构化数据。一个简单的 protobuf 文件可以是这样的:
1 | message Person { |
具体的语法可以参考Google 的文档 proto2 和 proto3。c++ 语言使用 protobuf 的示例可以参见Protocol Buffer Basics: C++ 文档,基本步骤总结如下:
参考: https://github.com/google/libprotobuf-mutator/blob/master/README.md
1 | git clone https://github.com/google/libprotobuf-mutator.git |
由于需要从Google下载一些源码,所以在 ninja check
的时候需要挂上代理,结果编译出错了,找不到 libxml2.a
,排查一下编译参数,发现需要添加编译静态库的参数
1 | diff --git a/cmake/external/libxml2.cmake b/cmake/external/libxml2.cmake |
修改后可以正常通过 ninja check
命令的所有检查。默认情况下 ninja install
会安装到 /usr/local 目录,因为考虑到后续需要给 afl+
使用,所以需要使用下的命令重新 cmake 一下
1 | cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON \ |
libfuzzer_macro.h
1 | #define DEFINE_TEST_ONE_PROTO_INPUT_IMPL(use_binary, Proto) \ |
调用路径为 DEFINE_PROTO_FUZZER
-> DEFINE_TEXT_PROTO_FUZZER
-> DEFINE_PROTO_FUZZER_IMPL
-> DEFINE_TEST_ONE_PROTO_INPUT_IMPL
-> LLVMFuzzerTestOneInput
-> TestOneProtoInput
。
最终还是实现了LLVMFuzzerTestOneInput
libfuzzer 的入口方法,使用 macro 可以少写不少代码非常方便,从这里就可以看出 fuzz 的 target function 必须和 LLVMFuzzerTestOneInput
的参数类型一致
1 | // fuzz_target.cc |
libfuzzer_macro.cc
1 | bool LoadProtoInput(bool binary, const uint8_t* data, size_t size, |
LoadProtoInput
返回 true
或者 false
,如果解析成功,将调用 TestOneProtoInput
,DEFINE_PROTO_FUZZER
macro 其实就是写 TestOneProtoInput 的实现。
这是 github 上一位同行写的学习 libprotobuf-mutator fuzzing 的文章,总体写的不错,但是其中有一些错误的地方,在实践过程中都记录了其中的修改。
文章:https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/1_simple_protobuf
先写一个简单的 protobuf 文件,test.proto
1 | syntax = "proto2"; |
使用 protoc
编译 protobuf 文件
1 | mkdir genfiles |
将自动生成两个文件
1 | ls ./genfiles |
写一个测试程序 test_proto.cc
1 | #include "test.pb.h" |
写 Makefile 来编译 test_proto.cc
1 | CXX=clang++ |
执行 make
后报错 ./test.pb.h:17:2: error: This file was generated by an older version of protoc which is,因为我们在编译的时候使用了 -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON
下载了新版本的 protobuf,所以出了这个错误。只好使用下载的 protoc 重新生成 test.pb.cc
和 test.pb.h
1 | ~/code/libprotobuf-mutator/build/external.protobuf/bin/protoc ./test.proto --cpp_out=./genfiles |
这次可以成功 make 了,实际执行的命令是
1 | clang++ -o test_proto test_proto.cc test.pb.cc /home/henices/code/libprotobuf-mutator/build/external.protobuf//lib/libprotobufd.a \ |
运行 ./test_proto
, 输出如下
1 | 101 |
harness.cc
1 | #include <stdint.h> |
其中 FuzzTEST 是我们需要测试的目标函数。
lpm_libfuzz.cc
1 | #include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" |
在文件的最开头导入 libfuzzer_macro.h
, 后面就可以使用一些宏来写代码了,DEFINE_PROTO_FUZZER
是关键的 fuzzer 入口。结构化变异部分 libprotobuf-mutator 已经完成了,需要实现的是一个由 protobuf 转需要的数据类型的函数,如上面的 ProtoToData
1 | TARGET=lpm_libfuzz |
make 后报错,找不到头文件
1 | /home/henices/code/AFL+/external/libprotobuf-mutator/include/libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h:24:10: fatal error: 'port/protobuf.h' file not found |
port/protobuf.h 来自 https://github.com/google/libprotobuf-mutator/blob/master/port/protobuf.h 修改 Makefile 如下
1 | TARGET=lpm_libfuzz |
修改 makefile 后,可以正常编译通过。经过我们上面的分析,不需要定义 DFUZZ=-DLLVMFuzzerTestOneInput=FuzzTEST
将这行删除掉,同样可以编译通过。
执行 lpm_libfuzz
运行正常
1 | ➜ ./lpm_libfuzz |
主要内容是将 libprotobuf-mutator 和 afl++ 结合起来,使用的 afl++ 的 custom mutator,值得一提的是在这个例子里,需要使用 -fPIC
参数编译 libprotobuf-mutator。
1 | cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON \ |
主要的步骤在 readme.md 中已经介绍得比较清楚了。
lpm_aflpp_custom_mutator_input.cc
是 afl++ 的 custom mutator shared libraryTEST
protobuf messagelibprotobuf-mutator
变异 TEST
protobuf messagePostProcessor
处理变异后的 TEST
protobuf message (非必要步骤)1 | extern "C" size_t afl_custom_fuzz(MyMutator *mutator, // return value from afl_custom_init |
mutator->Mutate(&input, max_size);
为真正起作用的核心代码
lpm_aflpp_custom_mutator_input.h
继承了protobuf_mutator::Mutator, 可以使用 libprotobuf-mutator 的 Mutate 方法1 | #include "libprotobuf-mutator/src/mutator.h" |
test_proto_serializer.cc
TEST
protobuf message,可以作为 fuzz 的初始化 testcase 使用vuln.c
漏洞测试程序
1 | #include <stdio.h> |
漏洞测试程序比较简单,只要第一个字节是 0xe8
或者 0x02
即可,libprotobuf-mutator 的变异在这个例子里效率并不高,所以需要使用 PostProcessor
来优化变异。
1 | TARGET=lpm_aflpp_custom_mutator_input |
Makefile 有瑕疵,这个章节的内容和 libfuzzer 没有关系,不需要链接 libprotobuf-mutator-libfuzzer.a
https://developers.google.com/protocol-buffers/docs/cpptutorial
https://github.com/google/fuzzing/blob/master/docs/structure-aware-fuzzing.md
https://github.com/google/libprotobuf-mutator/
https://llvm.org/docs/LibFuzzer.html
https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning
https://www.youtube.com/watch?v=7Ysy6iA2sqA&ab_channel=OffensiveCon
gogs 使用了也有一年多了,小团队使用基本还行。有几个问题,第一界面代码 merge 有问题,第二不支持代码 review,
如果能解决上面两个问题就好用很多了。下面两段是年前折腾 gogs 的记录,没有啥技术含量,只是做个备份。
https://github.com/Kos-M/GogsThemes 提供了两款皮肤,文中给出的方法要修改 gogs 配置,直接使用 TamperMonkey 就可以了。
1 | // ==UserScript== |
使用后效果图
gogs 已经有一年多没有提供二进制的安装包了,看了改进不少,就尝试了源码升级。
参考 https://gogs.io/docs/installation/install_from_source#%E6%B5%8B%E8%AF%95%E5%AE%89%E8%A3%85
参考 Google 官方文档,执行下面命令就可以了。 https://go.dev/doc/install
1 | wget https://go.dev/dl/go1.17.6.linux-amd64.tar.gz |
1 | # 克隆仓库到 "gogs" 子目录 |
编译过程会下载文件(需要自备梯子),编译完成后将在 gogs 工作目下生成 gogs 可执行文件
gogs 源码的 Makefile 提供了打包命令,执行 make pack
即可,将在 release 目生成 gogs.20220112095054.zip
将 gogs.20220112095054.zip 解压,这就类似 gogs 的二进制升级了 https://gogs.io/docs/upgrade/upgrade_from_binary
1 | mv gogs gogs_old |
gogs 0.13 的配置已经发生了变化,如果不修改配置执行 ./gogs web
会出现错误
1 | 2022/01/12 09:40:06 [ INFO] Gogs 0.13.0+dev |
看错误像是在连接 mysql 的 3306 端口,可是配置文件设置的是使用 sqlite,非常困惑。上网搜索后证实是 gogs 0.13 的配置文件的字段修改了。
最关键的两个字段是数据库相关的 DB_TYPE
改为 TYPE
, PASSWD
改为 PASSWORD
修改后 custom/conf/app.ini
后,执行 ./gogs web
一切正常。
向大家安利一款 markdown 笔记软件, VNote https://github.com/vnotex/vnote
此软件目前已经 1300 多个commits 了,做为一个有些开源软件维护经历的人,深感不易。
用了太多 markdown 笔记软件,此软件使得最为顺手,尤其作为程序员 vim 模式 让我感到非常舒服,
大量图表的支持比如 UML 流程图,让我用起来很顺手。
Vnote 分为两个开发阶段,阶段一 vnote2 已经开发完成:https://github.com/vnotex/vnote/tree/vnote2
现在处于第二个开发阶段:https://github.com/vnotex/vnote
据说后续会出收费版本,但目前看还需要很长的一段时间了。
我前后尝试过各种笔记软件,我理想的软件有几点:
最后,终于发现了 VNote,有点惊喜。在 Linux 下编译 VNote 显示有明显改进,下面是编译的方法:
将 Qt5.9 安装到 /home/henices/Qt5.9.0/
git clone https://gitlab.com/fcitx/fcitx-qt5.git
准备编译脚本 build_linux.sh
, 指定下载的QT
1 | QTDIR="/home/henices/Qt5.9.0/5.9/gcc_64/" |
使用下面命令编译
1 | chmod a+x ./build_linux.sh |
将生成的 libfcitxplatforminputcontextplugin.so copy 到/home/henices/Qt5.9.0/5.9/gcc_64/plugins/platforminputcontexts/
1 | git clone https://github.com/tamlok/vnote.git vnote.git |
build_linux.sh
1 | QTDIR="/home/henices/Qt5.9.0/5.9/gcc_64/" |
使用下面命令编译
1 | chmod a+x ./build_linux.sh |
sudo make install
Fedora 升级到 35 后,Vnote 出现了一系列问题
vnote 的阅读模式不能正常显示 (Qt 5.12.11)
解决这个问题需要禁用 Qtwebengine 的 sandbox
1 | ./vnote --no-sandbox |
最终解决问题的方法是下载 Qt5.15.2 重新编译 Vnote, Qt 从 5.15 开始不提供离线安装包,非常不方便。
官方提供的在线升级包如果太新只能安装 Qt 6,所以必须下载老版本的 online installer
https://download.qt.io/archive/online_installers/4.0/qt-unified-linux-x64-4.0.1-1-online.run
具体内容可以参考 https://github.com/vnotex/vnote/issues/1942 的讨论
使用 Qt 5.15.3 编译 VNOte 后,出现下面的报错
1 | [695784:695784:0401/181224.580254:ERROR:network_service_instance_impl.cc(286)] Network service crashed, restarting service. |
bug 在这 https://bugreports.qt.io/browse/QTBUG-91715 可以先使用环境变量救急一下
1 | QTWEBENGINE_DISABLE_SANDBOX=1 QTWEBENGINE_CHROMIUM_FLAGS=--lang=de ./vnote --no-sandbox --disable-gpu |
https://tamlok.gitee.io/vnote/zh_cn/#!docs/%E5%BC%80%E5%8F%91%E8%80%85/%E6%9E%84%E5%BB%BAVNote.md
用了 Logseq 一段时间了,做个简单的总结,国内的很多文章,在我看来还是不够简单明了, 本文大致介绍了 Logseq 比较常用的一些功能的使用。
可以把记录的知识点当作卡片来记忆,用过 Anki 的同学,应该都比较熟悉了,使用的记忆算法为 SM-5
要将一个 block 记为卡片非常简单,使用 #card
标签就可以了。
有些卡片可能是归属同一个大类,这时候就可以使用卡片组了。像我上面这个例子中,要记忆的单词都在 英语单词积累
下,就可以使用语法 {{cards 英语单词积累}}
效果如下图,
可以看出我已经积累了7张卡片了。
要背诵需要记忆的卡片时,单击左侧的 Flashcards 就可以了,使用方面没有什么特别的地方,有三个选项可以选择。
皮肤就是青菜萝卜各有所爱了,推荐两款我自己比较喜欢的的皮肤。
Github 仓库地址如下:
https://github.com/pengx17/logseq-laurel-theme
https://github.com/tobealive/logseq-allday-theme
有两种方法可以设置皮肤:
使用 custom.css,打开 Settings -> General -> Custom theme 点击 custom.css
复制 css 内容,保存退出即可。
使用插件系统,则需要先把插件系统打开,Settings -> Advanced -> Plug-in system 。打开插件系统后,可以直接使用
Plugins -> Marketplace -> themes 选择你喜欢的 theme 点击 Install
就可以了
不过还是推荐使用 Logseq 自带的插件管理系统来安装,可以自动升级比较方便,切换皮肤可以点击右上角 三个点 -> Themes 选择皮肤。
使用 Logseq 插件同样是两种方法:
使用插件系统的方法和上面安装皮肤的步骤大致相同,依次点击 Plugins -> Marketplace -> Plugins ,选择插件点击 Install
即可。要加载 unpacked plugin
首先要打开开发者模式 Settings -> Advanced -> Developer mode , 设置为打开。打开后使用插件管理系统 Plugins -> Installed -> Load unpacked plugin 选择相关目录就可以了。
具体的插件可以参考 https://github.com/logseq/awesome-logseq#Plugins 记录的插件都挺不错的。
值得一提的是,插件系统的网络不太稳定(总所周知的原因),使用代理会方便一些。
1 | https_proxy=127.0.0.1:3128 ./Logseq --proxy-server=http://127.0.0.1:3128 |
安装插件可能会出现 timeout 错误,多重试几次就应该可以安装上了。
query 算是 Logseq 的高级功能了,我用的也不多,输入 /query
回车就可以自动进入 query 了,具体的语法很灵活可以参考:
https://logseq.github.io/#/page/queries
油管上有相关 video,大家可以参考一下:
https://www.youtube.com/watch?v=GDauxjx_bdA&ab_channel=OneStutteringMind
https://www.youtube.com/watch?v=qQ8DzumRZkM&ab_channel=OneStutteringMind
Logseq 的功能还是挺多的,两篇文章也不可能全部介绍完,官方文档总是最好的资料:https://logseq.github.io/#/page/Contents
https://logseq.github.io
https://www.usmacd.com/2022/02/21/logseq/
paper: https://www.s3.eurecom.fr/docs/fuzzing22_fioraldi_report.pdf
字段 | 内容 |
---|---|
样本名 | BankBot |
MD5 | 3c42c391bec405bb28b28195c2961778 |
SHA256 | 93b64019ee48177889d908c393703a2a2fe05ca33793c14b175467ce619b1b94 |
文件类型 | APK |
这是一个以盗窃信用卡用户密码为主要目的的bot。安装后显示为Android图标。打开App后
会以Android系统更新的形式,诱导用户操作达到常驻系统的目的。
1 | <receiver android:name="com.android.market.Autorun"> |
Autorun
1 | package com.android.market; |
开机将启动 Schedule 服务
1 | public int onStartCommand(Intent intent, int flags, int startId) { |
Schedule 服务使用alarm manager 注册一个定时任务。这个定时任务由NetworkController完成。
时间间隔由配置文件interval决定。
com.android.market.FileController
1 | static final boolean fileExists(Context context, String filename) { |
1 | static final void hideApp(Context context, boolean hide) { |
1 | public void onCreate() { |
1 | AdminX.this.getSystemService("keyguard").newKeyguardLock("ANDROID").disableKeyguard(); |
1 | public void onReceive(Context context, Intent intent) { |
通过网页 http://www.sberbank.com/news-and-media/contacts 中的信息我们可以知道:
8005555550 4955005550 这两个号码 sberbank 的号码,在俄罗斯拨打免费。
1 | String v10 = "8005555550; 4955005550;"; |
1 | private StringBuilder getCallLog() { |
1 | private StringBuilder getSmsLog() { |
1 | private StringBuilder getHistory(Uri historyUri) { |
当用户打开Google Play 应用时,打开伪造的Activity,诱使用户输入信用卡信息。
com.android.smali3
1 | public void onDestroy() { |
服务被停止,立即重启,无法停止。
Bankbot 申请 Device Admin 权限,无法被正常卸载。
1 | > adb shell pm uninstall com.android.market |
这个一个非常流氓的做法,具体的做法是如下面的代码:
1 | public class AdRec extends DeviceAdminReceiver { |
重写 DeviceAdminReceiver 的 onDisableRequest 方法。使用 Thread.sleep 方法使用户
无法操作界面,在此期间采取 Activity 切换的方法绕开取消激活的步骤。
这里出过几个问题,
通过界面劫持,诱使用户将App设置为设备管理器。从下图中可以看见Continues按钮其实
是设备管理器的激活按钮。
Bankbot 以固定时间轮询的方式向C&C服务器请求命令,命令的格式为json格式。从代码中
可以得到json字段的信息。
1 | private static final String FIELD_ACTION = "action"; |
返回报文
401
请求报文
1 | POST /p/gate.php HTTP/1.1 |
响应报文
1 | HTTP/1.1 200 OK |
1 | POST /p/gate.php HTTP/1.1 |
1 | HTTP/1.1 200 OK |
返回的命令为json 格式,主要的指令有下面几个,
指令 | 含义 |
---|---|
401 | 要求 bot 注册 |
call_log | 获取电话记录, 发送到C&C server |
sms_history | 获取短信内容,发送到C&C server |
browser_history | 获取浏览器书签,发送到C&C server |
url | 访问url 链接 |
server | 更换C&C server |
intercept | |
server_poll | 更新从服务器获取命令的时间间隔 |
mayhem | |
calls |
监视服务了大半天,没有收到有效指令,看来不是特别活跃。
这个App的清除非常费劲,原因就是注册为设备管理器的app不能卸载,而这个App又使诈
不让我们取消设备管理器,估计只有root的机器会好处理一些。
BankBot 样本,代码编写的相当规范,风格严谨,是正规程序员的作品。但行为非常流氓,
很顽固,不容易清除。所以遇到申请device admin 权限的程序一定要小心谨慎,以免不良
后果。而Android的界面劫持也是一个严重的问题,估计后续利用这些技术的恶意App的数量
会越来越多。