XcodeGhost, 墙, 全民编程, 以及未来

这些天 XcodeGhost 闹得沸沸扬扬. 作为一个好歹写程序的年头比 Twitter 或者 Weibo 上大多数人长的老程序员来说, XcodeGhost 本身其实并没什么高深之处, 也没有什么出乎意料的巨大危害. 甚至, 把它称为病毒也是错误的, 最多不过是个 malware 而已. 并且, 相对于国内 Windows desktop 以及 Android 系统里的 malware 们而言, XcodeGhost 太小儿科了. 好歹 iOS 的 sandbox 还控制着权限, Windows 全家桶们可是早就把你的底裤都翻光了. 没见着有这么激动嘛.

我赞同云风的观点, 这个玩意跟你 link 了一个谁谁谁的什么分析跟踪, 广告展示, 乃至于流行的支付, 分享等等的 SDK 进去没有任何差别. 技术一点说, 两者都是把一些代码加入到了你的应用中, 并且在某些时候会得到执行.  弹窗骗用户帐号密码? 都可以. 发送一些用户信息到远端服务器上? 都可以. 安装企业证书签名的 App? 都可以. 顺便说一下, 国内对企业证书的滥用才是比 XcodeGhost 更大得多危险得多的安全漏洞.

究其原因不能不说到墙. 然而不是说把责任都推到墙上就完事了的. 需要想一想为什么这样, 以及这又反映了什么.

首先, XcodeGhost 这个东西也是只有在国内这个环境里才会造成这么大范围的传播和扩散. Yes, 墙功不可没. 不过试想一下, 假设现在把墙撤了, 我认为 XcodeGhost 还是会同样大量迅速扩散的. 对于多年来习惯于四处下载盗版音乐电影软件的毫无职业素养和基本常识的你国众多小白程序员和产品经理来说, 对, 像 adoal 说的, 连免费软件都要盗版的人来说, 扔到迅雷上去或者从百度云盘拉, 必然会是比从 Mac App Store 或者 Apple developer site 下载安装更优先的选择. 再往深了想原因就是多种互相纠缠在一起了, 恕不赘述. 想探讨的请我吃饭咱们边吃边聊好了. 哈.

然后回过来说墙. 经过从计算机萌芽期开始长期不懈的盗版洗礼, 以及 10 年左右的强有力的寡妇网封锁. 你国小白们, 不光是普通用户, 连程序员都是, 已经不知不觉地形成了相当完整的墙内思维了. 搜索上百度, 软件下盗版, iOS 用 XX 助手, Malware 遍地的 android 商店们就更不用说了. 大家的整个计算机生存环境已经是与你国以外用户完全不同的一个环境了. 很好, 非常好. 我觉得可以说, 大中华局域网已经基本完成了. 别说我危言耸听, 看看: 与世界隔离, 需要的所有东西都可以在内网设法找到无论什么途径来源如何, 这不是局域网是什么? 说件更悲哀的事, 跟十几岁的孩子们聊天, 已经几乎没有人知道 Google 是什么了. 这不能怪他们, 一个不能访问的网站, 自然就相当于不存在. 物理封锁其实还不算什么, 思维被封锁了, 才是真正的被封锁. 就如今的情形看, 我持悲观态度.

这个问题就到此吧, 我比较不喜欢煽情, 无论是热烈吹捧还是血泪控诉. 有脑子的人自己会去体会. 别老替别人哭和笑.

然后是全民编程. 这个话题这几年热得发烫. 然而对照 XcodeGhost 干了什么, 再想一想. 至少我觉得在目前, 全民编程这个想法很傻冒, 跟天真, 十分类似于别有用心的人提出来的. 连目前算是专业的程序员们都缺乏基本的编码常识, 你让见到随便哪个提示框就乖乖地把自己的帐号密码输进去的“民”来编程? 别说我阴谋论, 至少我是绝对不敢用这种民编出来的程的.

说到这里就是 IoT 了, 全民编程是在这个背景下提出来的. 我相信未来是人机结合体的时代, 但是安全是最大的问题. 从这个意义上讲, 未来还是有漫长的路要走, 因为, 信任这一安全上至关重要的点, 至今还是很难保证的. 是的, 我信任从 Mac App Store 安装的 Xcode, 但是我无法确认别人也是从 Mac App Store 安装的而不是从迅雷或者百度下载的带有 XcodeGhost 的. 所以, 这还是个难题, 除非所有代码都是我自己写的, 问题是, 我写得过来吗?

iOS BLE application restore

According to Apple’s documentation, Bluetooth related app can assign a restore identifier to itself so that it can be re-launched by system when BLE events arrived and the app has been killed by System. I made a test on this and found some facts Apple didn’t describe it clearly.

  1. If the app got killed by system due to resource limitation, it exactly can be re-launched, as Apple’s Core Bluetooth Programming Guide described.
  2. If the app got killed by user sliding up the app card away, it won’t be relaunched
  3. If the app connected to a bluetooth peripheral, it looks like the system assigned it a high priority so it is unlikely to be a candidate when system needs killing something.
  4. After centralManager:willRestore: method, centralManager:didUpdateState: is always got called,  so let the latter handle both the cases of normal launching and re-launching by system is OK.

Therefore, there is still no safe way to handle BLE communications in background since user can always kill the app, and it is usual for us iPhone users.

Just found 2 issues in apple’s assembler for arm64

1) The classic ‘@‘ comment indicator is not recognized in -arch arm64 mode. Both ‘;‘ and ‘//‘ are permitted. I remembered ‘@‘ was acceptable in armv7 age. So the world changes so fast…

2) As ARM’s instruction reference manual, the instruction ‘movi‘ has a format as

MOVI Vn.<T>, #uimm8{, LSL #shift}

But as reported error if we omitted last part. So to make assembler work, I have to append a ‘LSL #0’ to the end. Feel somewhat stupid, for both the assembler and myself 🙂

objc x86_64 ABI (Call convention)

As I am doing a bit reversing job on OSX, I looked it up and wrote it down here as a backup.

self:  rdi
selector: rsi
arg0: rdx
arg1: rcx
arg2: r8
arg3: r9

 

 

Android SurfaceView: can be used for media or direct access, but not for both.

That is, if you have an instance of SurfaceView, you can use it for video/camera, or use it for direct access as a buffer, but you cannot reuse it for media after you already accessed it through either ANativeWindow API or any other internal ways.

The reason is in ASOP code Surface.cpp. Surface connected to CPU if it once got locked, which is a necessary step to access its internal buffer. But it only got disconnected in  destructor. On other side, if you bind the Surface to media, it checks the connection status and return an error when it found it has already been connected to CPU.

So, if you need a SurfaceView for both purpose, you have to destroy the old, assuming it is for direct access, and create a new one for media.

So many traps there…

Simply, a .so compiled by android ndk r9 gcc 4.6 crashed on loading in function __check_for_sync8_kernelhelper.

After looking up the issue in Google, I found this issue has been reported to Google: https://code.google.com/p/android/issues/detail?id=58476. Unfortunately no solution at present.

Basically it is an libgcc issue depending on linux kernel version. Lower kernel version lacks the symbol that libgcc in 4.6 or higher needs. For example, the Galaxy Nexus I am just testing app on.

 

So,

1) Avoid using 64bit atomic operation built in gcc, if you can control everything in your codes.

2) Using gcc 4.4.3. For ndk r9 there is a legacy toolchain package in a separated download link.

Why so many latencies in BB10 audio playback? Why we always get underrun in audio data feeds?

They are two faces of one same issue.

If you started coding audio playback from reading PlayWav sample in BlackBerry’s github repository, you will find there are long latencies in audio playback, that is, about 5s after you fed data, you can hear the sound. But why? BB10 uses ALSA’s libasound as its audio API but the documentation and description are very little. So after many changes here and there, many trials and inspections, I got what controlled the latency.

snd_pcm_channel_params_t.buf.block.frag_max;

In PlayWav sample, this field is set to -1, which returned a large number in it from call of snd_pcm_plugin_params(). So we can set this field to a small number to reduce the latency. Indeed it is said that RIM recommends 5 but I don’t know whether it is true and I cannot remember where I found it.

Anyway, a number like 3 or 5 can exactly reduce latency to some small value so that our ears cannot find it. But another strange behavior occurs then: we got UNDERRUN frequently. At that time, if we set snd_pcm_channel_params_t.stop_mode to SND_PCM_STOP_STOP, the playing back stopped after a short time interval; if we set snd_pcm_channel_params_t.stop_mode to SND_PCM_STOP_ROLLOVER, the playback will repeats data in a few last buffers.

The latter issue is due to thread priority. QNX’s io-audio drivers runs playing back in very high priority so it is very easy to make your data UNDERRUN if you just run your data feed thread in a normal priority. In some discussion somebody recommends set data feed thread to 50 and in some other codes the value was set to 18 or so.

Conclusion: to make audio playback smoothly and easily, 1) set frag_max to 5 or another small value but too small may cause UNDERRUN issue. The field controlled data buffering – yes, it equals to audio latency on other side – in implementation of audio playbacks. 2) raise your data feed thread priority to some higher value. Normal thread runs on 10 and audio playback thread runs on a higher priority. Set to higher to avoid data UNDERRUN.

 

iOS7: We cannot modify UIAlertView directly now.

From iPhoneOS 1 to 6, each experienced iOS programmer knows how to modify UIAlertView for appearance customization. For example, to add some UI elements like UILabel or a secure UITextField for password input, etc. One of our little tool keyOne used this trick.

But this doesn’t work in recent iOS7 beta. The reason is simple after checking view hierarchy in debugger. This is keyWindow when a UIAlertView popped up:

(lldb) po [[UIApplication sharedApplication] keyWindow]
<_UIModalItemHostingWindow: 0xb2dba70; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0xb2d5f20>; layer = <UIWindowLayer: 0xb2dbb50>>

and a view for alert exactly

(lldb) po [[[[[UIApplication sharedApplication] keyWindow] subviews] objectAtIndex:1] subviews]
<__NSArrayM 0xc975e80>(
<UIView: 0xb2e83a0; frame = (0 0; 320 568); layer = <CALayer: 0xb2e8770>>,
<_UIModalItemRepresentationView: 0xb2e5de0; frame = (25 184; 270 200); layer = <CALayer: 0xb2e5da0>>
)

The UIAlertView returned to caller is a stub only

lldb) po alertView
<PasswordPrompt: 0xb2c7f80; baseClass = UIAlertView; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0xb2a1cc0>>

The view has zero size so we certainly cannot customize it.

 

QNX’s problem 1: Mix C and C++ code.

It looks like some standard C header files like math.h in QNX toolchain contains C++ elements around by #ifdef __cplusplus preprocessor directives. That will bring some troubles when you need to mix C and C++ in one project.

Let’s see an example. Assume we have a C header file c.h and a C source file c.c, like below

c.h

#ifndef __C_H__
#define __C_H__
#include <stdint.h>
#include <math.h>
struct struct_c {
 int32_t dummy_field;
};
int func_c(struct struct_c * c);
#endif // __C_H__

c.c

#include <stdio.h>
extern "C" {
 #include "c.h"
}
int main()
{
 struct struct_c c;
 c.dummy_field = 1;
return printf("func_c() = %d\n", func_c(&c));
}

Compile them into a shared library libccc.so:

mbp17:qnx_header_test lee$ /Applications/bbndk/host_10_0_9_52/darwin/x86/usr/bin/ntoarmv7-gcc -c c.c
mbp17:qnx_header_test lee$ /Applications/bbndk/host_10_0_9_52/darwin/x86/usr/bin/ntoarmv7-gcc -shared c.o -o libccc.so
mbp17:qnx_header_test lee$ ls -l libccc.so
-rwxr-xr-x 1 lee staff 4725 11 1 11:36 libccc.so

That’s OK.

Now we have another C++ file named cc.cpp

#include <stdio.h>
extern "C" {
 #include "c.h"
}
int main()
{
 struct struct_c c;
 c.dummy_field = 1;
return printf("func_c() = %d\n", func_c(&c));
}

It is very simple. Let’s try to compile it. We got tons of errors! Some listed as below:

mbp17:qnx_header_test lee$ /Applications/bbndk/host_10_0_9_52/darwin/x86/usr/bin/ntoarmv7-g++ -c cc.cpp 2>&1 | more
In file included from /Applications/bbndk/target_10_0_9_386/qnx6//usr/include/math.h:4:0,
 from c.h:5,
 from cc.cpp:4:
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:116:1: error: template with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:150:1: error: template with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:157:1: error: template with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:163:1: error: template specialization with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:200:1: error: template with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:207:1: error: template specialization with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:212:1: error: template specialization with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:218:1: error: template with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:224:1: error: template specialization with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:229:1: error: template specialization with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:234:1: error: template specialization with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:239:1: error: template specialization with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:245:1: error: template with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:251:1: error: template specialization with C linkage
/Applications/bbndk/target_10_0_9_386/qnx6//usr/include/xtgmath.h:256:1: error: template specialization with C linkage
I

Check error messages. Obviously math.h includes xtgmath.h internally. In latter some C++ template definitions are there around #ifdef __cplusplus directives. But in compiler’s view, though we wrapped #include “c.h” with extern “C” – it is necessary for linking, __cplusplus is still defined for C++ program. So, templates were incorrectly included into a pure C linkage enviroment.