iOS系统逆向工程之神探侯佩智破量子矩阵

在任何一部编程悬疑动作片里,每一个超级英雄都有一个颓废的开始…

本故事纯属虚构
如有雷同洗洗睡吧

警告:未经允许禁止转载!!!

楔子

在这里插入图片描述

未知星球。

雨还在下,漆黑的乌云压抑的想吐。

极度的黑暗中,一枚红点忽明忽暗…

一团黑影斜靠着墙壁,使劲的吐着烟圈…

墙壁上到处都留存着纳米激光射线刻着的"S w i f t",“S w i f t U I”,“C o m b i n e”,"i O S"等残破烙印,仿佛还在宣告183年前那场世纪大战有多么惨烈…

“卧底雨燕党已经211天了,还是没能查出到底他们是怎么把量子矩阵传递出去的,这样的话会来不及的…”

与此同时,在地球…

在这里插入图片描述

“这么说,你们只是搞清楚了它有两个特性,其它的毛线都不知道?”,局长悻悻的说。

“是的,量子矩阵(以下简称量矩)能根据空间自动调节自己的尺寸,它具有抗压和抗拉两个特性,但是,局长…”

大屏幕上适时的打出以下两行大字:

  • 抗拉 Content Hugging Priority
  • 抗压 Content Compression Resistance Priority

“但是你们就是不知道它们是怎么被修改的???!!!”,局长有点压不住火了。

“知…知道,通过setContentHuggingPriority:forAxis:和setContentCompressionResistancePriority:forAxis:两条夸克隧道,可是再往下就不知道了…”,行动处长战战兢兢的说。

“为什么该死的燕子党突然会调整量矩?我们的人泄露了消息???”

“是…是的…查找内奸的行动已经秘密展开了…”

“那么现在我们只能把宝押在侯探员身上了?”

“恐怕如此…”

“最好是这样,否则你们下半辈子都会烂在黑洞阿尔法里…”

“阿尔法…还阿凡达呢,你妹的…”,处长脸上保持惶恐,可心里也是有点小脾气的。

在这里插入图片描述

“侯佩,侯探员…你TM到底在哪啊?”,局长眼睑不动声色地抽动了一下,转过身去,透过巨大的飘窗直视着远方耸入云端的徽塔,但却又好像什么都没看到…

星际坟场

1亿8千万光年之外…

遥远的苹果星云中心,看似空空如也。

在这里插入图片描述

其实并不是!

如果能展开空间的第13维度,你会发现一颗渺小的中子星隐藏在其中,外形像极了一颗咬了一口的苹果。它就是臭名昭著的雨燕党老巢—星际坟场。

100万年前就是这名不见经传的小小雨燕党,在这里摧毁了红极一时的欧碧姐C党派,迅速崛起,称霸一方,留下一片上古文明的残骸焦土。

星际坟场B2区地下的堡垒中,斜躺着一位身材硕大的党魁,一张黢黑的老脸很是享受。在他怀里坐着一个身材娇小的红发妓女,不时发出咯咯娇笑。

墙上全息光子电视中用最大音量播放着最新出的爱情动作片《东京还是热》…

“你就给我看一下那个盒子嘛,蟑螂大爷…”,女子按着党魁的鼻子说,一脸放荡。

"别胡闹!"站在旁边一个佝偻着的小混混连忙上前伸手喝止着。

“死侏儒,你敢碰我…”,女子微嗔道。

小混混站在那里不敢动了,低下头微微斜眼揣测着BOSS的意图。

“没事,没事,不过这个可不太行哦…”,长得像蟑螂的党魁阴阳怪气的说。

话音未落,"老蟑螂"突然眉头一皱,双眼一翻,身子像一滩烂泥般瘫软下去…

小混混急忙推开红发女子,扶起"老蟑螂",只见他的鼻子外侧有一个暗红色的小洞,向外汩汩淌着血水。

“你…你干了什么!?”,越害怕小混混的脸显得越丑陋。

“别乱动,否则你也一样下场…”,只见红发妓女掏出一只电击约束环,麻利的套在小侏儒手上,小侏儒瞬间失去了反抗能力。

红发女子似乎很满意小侏儒错愕的表情,从左胸的暗兜中掏出一根吸取器,对着"老蟑螂"的左眼猛地扎了下去…

在这里插入图片描述

“你疯了…”,小混混直冒冷汗,使劲的将鼻涕吸了回去,心想:“这女人长的挺好看,心怎么这般狠毒呢???”

只听嗖的一声,眼球应声而起,奇怪的是没有流半滴血,原来是一只假眼。

红发女子轻轻捏碎假眼球,从里面捏出一只微型手电筒状的东东,按下开关,射出一道紫红色的光束。

女子撸起左臂,露出白皙的胳膊,上面纹有几个小字, 红光轻轻扫过小字,只听滴滴滴三声,紫红色的光束逐渐变大,成为一个人型大小的光圈。

小侏儒顿时吓得尿了出来,黄浊的尿液顺着裤腿流到地上…, 因为他看清了那几个纹着的小字:

Objective-C Forever!!!

叹息之墙

在这里插入图片描述

红发女子表情瞬间变得异常庄严神圣,只见她缓缓摘掉红色的长假发,露出一头黑色的短发,浑身白皙的皮肤在紫色的光圈掩映下,微微泛红。

“你…你是欧碧姐C党的后人…”,小侏儒貌似有点惊慌。

“闭嘴…你不配说我们党的名字…”,不待说完,C党美女矮身就要进入光圈…

“不…等等…你不能进去…会送命的…”

“什么?”

“你没法突破叹息之墙,会被撕碎的…除非…”

“除非什么…”

“除非你有System V ABI接口的钥匙…”

“哈哈,你以为我不知道么…你干嘛这么关心我?”

“因为…因为你长得好看…”

C党美女嫣然一笑,随即正色道:“你这侏儒,懂个屁!”

正说着,她随手从右胸的暗兜里掏出一个纳米投影仪,打开开关将画面投射到墙上:

The calling convention of the System V AMD64 ABI is followed on Solaris, Linux, FreeBSD, Mac OS X, and other UNIX-like or POSIX-compliant operating systems. The first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, and R9, while XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6 and XMM7 are used for floating point arguments. For system calls, R10 is used instead of RCX. As in the Microsoft x64 calling convention, additional arguments are passed on the stack and the return value is stored in RAX.

小侏儒本想问:“你是机器猫么?胸里面哪来这么多兜兜呢?”,但还是抿抿嘴忍住了…

在这里插入图片描述

“你懂这种语言吗?”,美女问道。

“不太懂…”

“这叫英语,英格利希”

“嗯…以前好像听BOSS说过,不是几千万年前就失传了么?”

“哼,自从上古时期一个叫瓷器的帝国统治全宇宙之后,瓷器语就成为全宇宙唯一的官方语言了,我们现在用的都是瓷器语的衍生语。不过那时候有些文字是用英语写的…”

在这里插入图片描述

“你怎么会知道这些,你到底是谁啊…”

美女没有理睬他,跳入光圈,口中念念有词: “XCode,XCode,急急如律令…setContentCompressionResistancePriority:forAxis:,断!”

投影仪文字瞬间定格在如下画面:

在这里插入图片描述

“比想象的难,矩阵接口内部果然用了跳转,那就是…”

美女自言自语的说:

“objc_msgSend…”

欧碧姐·米思婕莎德

在这里插入图片描述

“不过有了ABI钥匙,还是可以解读的…”

美女心里默默演算起来…

“矩阵内部几乎所有隧道都会被objc_msgSend包装,所以setContentCompressionResistancePriority实际调用形式是…”

objc_msgSend(self,SEL,priority,axis)

“再根据ABI接口规范,那么就可以得到各个输入参数的值了…”

self: rdi 0x00007ff428512da0

SEL: rsi 0x00007fff52751fe3

priority: xmm0 40 E0 00 00

axis: rdx 1

美女已不顾目瞪口呆的小混混,口中继续念着:“XCode,继续,再断!”

投影仪画面立即变换为如下内容:

libobjc.A.dylib`objc_msgSend:
->  0x7fff513f7780 <+0>:   testq  %rdi, %rdi
    0x7fff513f7783 <+3>:   jle    0x7fff513f77e8            ; <+104>
    0x7fff513f7785 <+5>:   movq   (%rdi), %r10
    0x7fff513f7788 <+8>:   movq   %rsi, %r11
    0x7fff513f778b <+11>:  andl   0x18(%r10), %r11d
    0x7fff513f778f <+15>:  shlq   $0x4, %r11
    0x7fff513f7793 <+19>:  addq   0x10(%r10), %r11
    0x7fff513f7797 <+23>:  cmpq   (%r11), %rsi
    0x7fff513f779a <+26>:  jne    0x7fff513f77a6            ; <+38>
    0x7fff513f779c <+28>:  movq   0x8(%r11), %r11
    0x7fff513f77a0 <+32>:  xorq   %r10, %r11
    0x7fff513f77a3 <+35>:  jmpq   *%r11
    0x7fff513f77a6 <+38>:  cmpq   $0x1, (%r11)
    0x7fff513f77aa <+42>:  jbe    0x7fff513f77bf            ; <+63>
    0x7fff513f77ac <+44>:  addq   $0x10, %r11
    0x7fff513f77b0 <+48>:  cmpq   (%r11), %rsi
    0x7fff513f77b3 <+51>:  jne    0x7fff513f77a6            ; <+38>
    0x7fff513f77b5 <+53>:  movq   0x8(%r11), %r11
    0x7fff513f77b9 <+57>:  xorq   %r10, %r11
    0x7fff513f77bc <+60>:  jmpq   *%r11
    0x7fff513f77bf <+63>:  jb     0x7fff513f7831            ; <+177>
    0x7fff513f77c1 <+65>:  movq   0x8(%r11), %r11
    0x7fff513f77c5 <+69>:  jmp    0x7fff513f77d1            ; <+81>
    0x7fff513f77c7 <+71>:  cmpq   $0x1, (%r11)
    0x7fff513f77cb <+75>:  jbe    0x7fff513f77e0            ; <+96>
    0x7fff513f77cd <+77>:  addq   $0x10, %r11
    0x7fff513f77d1 <+81>:  cmpq   (%r11), %rsi
    0x7fff513f77d4 <+84>:  jne    0x7fff513f77c7            ; <+71>
    0x7fff513f77d6 <+86>:  movq   0x8(%r11), %r11
    0x7fff513f77da <+90>:  xorq   %r10, %r11
    0x7fff513f77dd <+93>:  jmpq   *%r11
    0x7fff513f77e0 <+96>:  jmp    0x7fff513f7831            ; <+177>

投影仪画面底部出现一段若隐若现的小字:

深入解构objc_msgSend函数的实现
https://www.jianshu.com/p/df6629ec9a25

“嗯,隧道内部果然是用上古时期的ASM语言描绘的,这应该是at&a而不是intel语种”,美女微微仰首伸眉。

“没错,第一行指令是比较rdi中的self地址是否为nil,是的话就直接跳到隧道末尾结束…这个testq用的好,像and却不会改变rdi里的值,只会置位Flag寄存器,比cmp 0,%rdi快多了…”

"但是接下来这些指令又是做什么的呢?"美女头皮略微发麻,后面一大串指令似乎超出她的分析能力,该从哪入手呢???

忽然,她意识到objc_msgSend会寻找self对象的isa表,然后再从方法地址缓存中寻找SEL对应的方法…不管怎样一定是间接跳转!!!

投影仪仿佛有自己的想法,偷偷在画面底部加上一小段话:

一个objc对象的isa的指针指向什么?有什么作用?
https://www.jianshu.com/p/05fecee74e97

美女并没有注意到这一点,只是将目光锁定在其中3个相同的语句上:

jmpq *%r11

“就是它们了…3个全部下断!继续…”,随着美女口中念念有词,屏幕继续变换着…

很快传送进入第1个jmpq,接着退出,最后停在了下面:

在这里插入图片描述

“怎么又是古老的ASM语言…不是很懂啊…不管了,再继续吧…”

很快投影仪显示了一行行很有规律的内容:

在这里插入图片描述

“是了,这就是跳转表了…再进去看看…”

在这里插入图片描述

“原来setContentCompressionResistancePriority会在隧道内部首先调用_contentCompressionResistancePriorities(),大致意思能看懂…它会判断是否有primitive值,如果有则返回,如果没有则返回default值…”

“那么,分别在_primitiveContentCompressionResistancePrioritiesValue()和_defaultContentCompressionResistancePriorities()下断,然后继续!”

投影仪机械的执行着美女的指令:

在这里插入图片描述
在这里插入图片描述

“啊哈…找到了…原来最终是调用objc_getAssociateObject来取得primitive值的啊…这个叫关联对象吧?”

“等等,如果我知道了关联对象的Key,我就可以绕过setContentCompressionResistancePriority直接写量子矩阵的属性了,同理对读操作也是一样。”

“那么就来克隆这个Key吧!回到第5张图,跳转到UIViewToContentCompressionResistancePrioritiesAssociatedStorageKey对应的内存!”

在这里插入图片描述

在这里插入图片描述

“怎么指向的内容都是0??? 哦…它只是一个const void * _Nonnull的指针而已,只要指针非空即可,至于里面的内容,那随便吧…”

这时小侏儒突然来了一句:“你到底是什么人?”

“我!? 哼…”,沉醉在演算的快感中的美女下意识的回答着:“我就是欧碧姐·米思婕莎德(后面简称米妹),欧碧姐C党的公主陛下…”

抽丝剥茧

在这里插入图片描述

周围的光线逐渐暗淡下来,从紫色的光圈中浮现出一个墨黑色的盒子,发出淡黄色的光芒…

盒子六面都浮现出同一个黑白相间的奇怪图案…

在这里插入图片描述

“如果有手机可以扫一下…”,米妹喃喃的说…

“什么意思?”,小侏儒丈二和尚摸不着头脑…

“不是说给你听的…”

“what???”

“哎,别管了…其实这个盒子就是量子矩阵…”

小侏儒惊了… “怎么在这?”

“我也不知道,这是苹果星云的创始者乔神留下来的远古遗骸之一,为了纪念他的女儿Lisa…”

米妹用纤细的手指轻轻触碰矩阵的边角,但是什么都没有发生…

“咦?怎么不行?”,米妹有点慌了……

投影仪显示的内容逐渐有了变化:

UIKitCore`-[UIView(UIConstraintBasedLayout) setContentCompressionResistancePriority:forAxis:]:
    0x7fff4902e765 <+0>:   pushq  %rbp
    0x7fff4902e766 <+1>:   movq   %rsp, %rbp
    0x7fff4902e769 <+4>:   pushq  %r14
    0x7fff4902e76b <+6>:   pushq  %rbx
    0x7fff4902e76c <+7>:   subq   $0x10, %rsp
    0x7fff4902e770 <+11>:  movq   %rdx, %rbx
    0x7fff4902e773 <+14>:  movss  %xmm0, -0x14(%rbp)
    0x7fff4902e778 <+19>:  movq   %rdi, %r14
    0x7fff4902e77b <+22>:  movq   0x40732ed6(%rip), %rsi    ; "_contentCompressionResistancePriorities"
    0x7fff4902e782 <+29>:  callq  *0x3d850740(%rip)         ; (void *)0x00007fff50b37400: objc_msgSend
->  0x7fff4902e788 <+35>:  movaps %xmm1, %xmm2
    0x7fff4902e78b <+38>:  cvtss2sd -0x14(%rbp), %xmm1
    0x7fff4902e790 <+43>:  testq  %rbx, %rbx
    0x7fff4902e793 <+46>:  je     0x7fff4902e7a9            ; <+68>
    0x7fff4902e795 <+48>:  ucomisd %xmm1, %xmm2
    0x7fff4902e799 <+52>:  jne    0x7fff4902e79d            ; <+56>
    0x7fff4902e79b <+54>:  jnp    0x7fff4902e7cf            ; <+106>
    0x7fff4902e79d <+56>:  movq   0x40732ebc(%rip), %rsi    ; "_setContentCompressionResistancePriorities:"
    0x7fff4902e7a4 <+63>:  movq   %r14, %rdi
    0x7fff4902e7a7 <+66>:  jmp    0x7fff4902e7c1            ; <+92>
    0x7fff4902e7a9 <+68>:  ucomisd %xmm1, %xmm0
    0x7fff4902e7ad <+72>:  jne    0x7fff4902e7b1            ; <+76>
    0x7fff4902e7af <+74>:  jnp    0x7fff4902e7cf            ; <+106>
    0x7fff4902e7b1 <+76>:  movq   0x40732ea8(%rip), %rsi    ; "_setContentCompressionResistancePriorities:"
    0x7fff4902e7b8 <+83>:  movq   %r14, %rdi
    0x7fff4902e7bb <+86>:  movaps %xmm1, %xmm0
    0x7fff4902e7be <+89>:  movaps %xmm2, %xmm1
    0x7fff4902e7c1 <+92>:  addq   $0x10, %rsp
    0x7fff4902e7c5 <+96>:  popq   %rbx
    0x7fff4902e7c6 <+97>:  popq   %r14
    0x7fff4902e7c8 <+99>:  popq   %rbp
    0x7fff4902e7c9 <+100>: jmpq   *0x3d8506f9(%rip)         ; (void *)0x00007fff50b37400: objc_msgSend
    0x7fff4902e7cf <+106>: addq   $0x10, %rsp
    0x7fff4902e7d3 <+110>: popq   %rbx
    0x7fff4902e7d4 <+111>: popq   %r14
    0x7fff4902e7d6 <+113>: popq   %rbp
    0x7fff4902e7d7 <+114>: retq

其中2列特别亮:

cvtss2sd -0x14(%rbp), %xmm1

ucomisd %xmm1, %xmm0

“这是setContentCompressionResistancePriority:forAxis:隧道的完整ASM表述,不过上面两行是什么意思?”,米妹又准备开始大脑验算…

“第一行很简单,就是 Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value,用今天的话来说就是扩展单精度浮点到双精度浮点…”,这时一个冷冷的声音说着。

“后面一句要跟它后面的两句连起来看.”,那个声音继续缓缓的说:

0x7fff4902e7a9 <+68>:  ucomisd %xmm1, %xmm0
0x7fff4902e7ad <+72>:  jne    0x7fff4902e7b1            ; <+76>
0x7fff4902e7af <+74>:  jnp    0x7fff4902e7cf            ; <+106>

“ucomisd指令用英格利希来说就是:Unordered Compare Scalar Double-Precision Floating-Point Values and Set EFLAGS。意思是无序双精度浮点数的比较,且比较的结果会置位标志寄存器的位。”

“哦!?是这样么?怎么个比较法呢?”,米妹很自然的继续问。

“这个…看一下指令集中Opertaion的描述:”

RESULT← UnorderedCompare(DEST[63:0] <> SRC[63:0]) {
(* Set EFLAGS *) CASE (RESULT) OF
    UNORDERED: ZF,PF,CF←111;
    GREATER_THAN: ZF,PF,CF←000;
    LESS_THAN: ZF,PF,CF←001;
    EQUAL: ZF,PF,CF←100;
ESAC;
OF, AF, SF←0; }

“上面2条指令首先jne判断Z标志是否不为0,若不为0则有两种可能:”

  1. UNORDERED: 比较的浮点数是无序的
  2. 或者它们是相等的

投影仪画面底部又浮现出一行小字:

What does ordered / unordered comparison mean?
https://stackoverflow.com/questions/8627331/what-does-ordered-unordered-comparison-mean

“至于究竟是哪种情况就要看后面那条jnp指令,它用来判断P位是否为0,若为0,那么只有一种可能:这两个数是相等的。所以这里来说ucomisd就是用来比较新设置的priority是否与之前设置的值相同,如果相同则没必要再设置了,也算一种优化吧…”

“哦…原来是这样…咦…你怎么知道!?”

小侏儒沉默…

“你刚才听到我是公主陛下怎么不吃惊???”,米妹仿佛有点看不懂这个小混混了,“你没听到我说话么,你聋啦,小侏儒!”

“其实我不是侏儒…”

“你说什么?”

“其实我是大熊猫…”

神探大熊猫侯佩

在这里插入图片描述

话音刚落,小侏儒双手箍着的电击约束环铛的一声掉到地上,只见他的身子舒展开,像充了气似的,瘦小的身子渐渐变得高大魁梧。他伸手慢慢将脸上的一层皮揭掉,原来猥琐丑陋的面容顿时变得异常英俊…

在这里插入图片描述

“原来你长的这般俊…”,米妹脸有点微微发烫…

“我知道,不是你一个人这样说…”

“我想给你生儿子…”

“摇号去…”

跑偏了,咱再倒回去重新说…


“你到底是谁?!”,米妹睁大了眼睛

“我是侯佩,我来自地球…”

“地球?难道你是卧底?”

“没错,我是卧底,代号大熊猫9527”

“我有点不信,刚才你都尿了…”

“我尿点比较低…”

“…”

“知道你为什么打不开量子矩阵么?”

“不知道,我明明已经解开秘钥了啊?!”,米妹有些沮丧…

“你必须更明确的告诉量子矩阵你的意图,而不是笼统说ASM语言层面上的东西,比如要告诉量矩用类C语言来还原setContentCompressionResistancePriority:forAxis:()隧道的话,是这个样子的:”

void setContentCompressionResistancePriority(priority:float, axis:Int){
	CGSize old_priority_size = _contentCompressionResistancePriorities()

	if axis == UILayoutConstraintAxisHorizontal{
		if float(old_priorities_size.x) != priority{
			NSValue *new_priorities = NSValue(valueWithCGSize:CGSizeMake(priority, old_priority_size.y));
			_setContentCompressionResistancePriorities(new_priorities)
		}
	}else{
		if float(old_priorities_size.y) != priority{
			NSValue *new_priorities = NSValue(valueWithCGSize:CGSizeMake(old_priority_size.x, priority));
			_setContentCompressionResistancePriorities(new_priorities)
		}
	}
}

“同理,我们可以还原_contentCompressionResistancePriorities():”

CGSize _contentCompressionResistancePriorities(){
	NSValue *priority_value = _primitiveContentCompressionResistancePrioritiesValue()

	if priority_value != nil{
		return priority_value.sizeValue
	}else{
		return _defaultContentCompressionResistancePriorities()
	}
}

“你…”,米妹做梦也没有想到过还要这样还原…

“最后是两个小隧道的还原:”

CGSize _defaultContentCompressionResistancePriorities(){
	return CGSizeMake(750.0 , 750.0)
}

NSValue* _primitiveContentCompressionResistancePrioritiesValue(){
	return objc_getAssociatedObject(key: (const void * _Nonnull)UIViewToContentCompressionResistancePrioritiesAssociatedStorageKey)
}

说完这些,矩阵盒子突然发出极其明亮的光,开始有规律的抖动起来…

“可以了…隧道已经开启了…”

“要坍塌了…不能待在这里了…”,侯佩目光如聚的盯着米妹,对方也含情脉脉的盯着侯佩…

“走吧…”,两人异口同声的说。

逃离

在这里插入图片描述

正当两人准备踏入光圈,量子矩阵突然开始剧烈摇晃起来,原来的隧道接口被无耻的关闭了。

“不好,接口被人关闭了, 我们回不去了…”,米妹急的差点掉出了眼泪。

“一定是Swift Runtime黑暗傀儡师干的!!! 不过没事,经过上面的演算,我们已经可以跳过Runtime系统隧道接口,随意修改矩阵空间了,别急,看我的…”

只见,侯佩不慌不忙的从袖子掏出一只激光笔,很快键入了以下内容:

#define UIViewToContentCompressionResistancePrioritiesAssociatedStorageKey 0x00007fff8992c082

id priority = objc_getAssociatedObject(v1, (const void * _Nonnull) UIViewToContentCompressionResistancePrioritiesAssociatedStorageKey);
    
NSValue *v = [NSValue valueWithCGSize:CGSizeMake(77, 121)];

objc_setAssociatedObject(v1, (const void * _Nonnull) UIViewToContentCompressionResistancePrioritiesAssociatedStorageKey, v, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

“太棒了,(77,121)量子位移正好可以容纳我们两个,走吧…”

“我不能和你走,我还有任务…”

“你…”,眼泪已经自米妹的大眼眶里晃来晃去了…

“有缘再见吧,我的公主…”,说完这句话,侯佩头也不回的离开了地堡…

留下米妹公主痴痴地望着他的背影,好像还想说什么,但最终没有说出口…

“再见了,我的大熊猫…”,公主心里默默念着,缓缓走进了矩阵光圈…

一声巨响,量子矩阵收缩的无影无踪…

一切好像从未发生过…

尾声

在这里插入图片描述

与此同时,地球.

滴滴滴…行动处长手腕上高级量子VPN联络器响了起来…

“嗯…都搞定了!?好的,知道了…”,挂掉联络器,处长长舒了一口气。

“好!干的不错…”,局长听了汇报后终于欣慰的笑了…

“那没什么事,我回去安排侯探员的下一步行动了…”

“嗯,去吧,辛苦了…”

处长转过身,快步走了出去…他不知道的是,背后局长脸上的笑容逐渐变得狰狞起来…

“这次傀儡术没有把你们干掉,下次你们不会这么幸运了…”,局长狞笑着,瞳孔浮现出一只血红的雨燕…

在这里插入图片描述

代码调试: 大熊猫侯佩
原创剧情: 大熊猫侯佩
文章撰写: 大熊猫侯佩
后期润色: 大熊猫侯佩
图片筛选: 大熊猫侯佩

(本集完)

大熊猫侯佩 CSDN认证博客专家 Swift Objective-C Xcode
非自由程序员,CSDN博客认证专家。
CSDN汇编板块版主, CSDN其他开发语言大版版主。

对App、以及Cocos2D、SpriteKit游戏开饶有兴趣。目前常用的语言是ObjC、Swift、Ruby等。不过看到编程艺术、ASM、逆向和C时依然欲罢不能。虽然不是,但喜欢黑客的思维和哲学,认为社会工程学很酷,但还没有实际用来撩过妹。
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页
实付 39.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值