使用零宽度字符进行追踪溯源

作者:{Esi}@ArkTeam

零宽度字符是隐藏不显示的,也是不可打印的,也就是说这种字符用大多数程序或编辑器是看不到的。最常见的是零宽度空格,它是Unicode字符空格,就像如果在两个字母间加一个零宽度空格,该空格是不可见的,表面上两个字母还是挨在一起的。

使用零宽度字符进行追踪实现原理:

一、向文本内容中加入指纹识别(正向Fingerprint)

1、提取登录用户的用户名,把其转换为二进制形式。这里,我们把用户名中的每个字母都转换为它对应的二进制形式:

const zeroPad = num => ‘00000000‘.slice(String(num).length) + num;

const textToBinary = username => (

  username.split().map(char =>

    zeroPad(char.charCodeAt(0).toString(2))).join(‘ ‘)

);

2、把这些经过二进制转换的用户名字母转换为零宽度字符。该过程中,二进制串中的每个1转换为零宽度空格,每个0转换为零宽不连字符(zero-width-non-joiner),每个字母完成转换后再在其后面加上一个零宽连字符(zero-width joiner ),然后再对下一个字母进行类似转换。

const binaryToZeroWidth = binary => (

  binary.split().map((binaryNum) => {

    const num = parseInt(binaryNum, 10);

    if (num === 1) {

      return ; // zero-width space

    } else if (num === 0) {

      return ; // zero-width non-joiner

    }

    return ; // zero-width joiner

  }).join() // zero-width no-break space

);

3、将最终转换过的”用户名”插入到需要保密的信息文本内容中。只需向信息文本内容中插入零宽度字符块即可。

二、向加入指纹识别的文本内容中提取用户名信息(逆向提取Fingerprint)

1、从加入指纹识别的文本内容中提取出零宽度形式的用户名。也就是删除那些我们看得到的文本信息,只留下零宽度字符。

2、把零宽度形式的用户名转换为二进制形式。这里我们根据之前添加的零宽度不连字符空格来分割整个字符串,我们会得到每个字母对应的与其零宽度字符等效的二进制字符,对所有零宽度字符进行迭代之后,我们就得到了二进制形式的1和0数字串。如果没找到对应的1或0,有可能是你忘了正向Fingerprint中步骤2中每个字母转换后还加了一个零宽连字符。

const zeroWidthToBinary = string => (

  string.split().map((char) => { // zero-width no-break space

    if (char === ) { // zero-width space

      return ‘1’;

    } else if (char === ) {  // zero-width non-joiner

      return ‘0’;

    }

    return ‘ ‘; // add single space

  }).join()

);

3、将二进制形式的用户名转换为实际可看的用户名文本。我们可以通过解析把1和0组成的二进制串转换为实际可看的用户名文本。

const binaryToText = string => (

  string.split().map(num => {

     String.fromCharCode(parseInt(num, 2))).join(”)

);

三、实验结果:

1、在chrome中输入usernameesi,并且复制文本


图1 向文本中加入指纹识别

2、在Safari中粘贴文本:可以追踪到用户信息


图2 提取用户信息

参考链接:

https://medium.com/@umpox/be-careful-what-you-copy-invisibly-inserting-usernames-into-text-with-zero-width-characters-18b4e6f17b66

https://github.com/umpox/zero-width-detection

发表评论

邮箱地址不会被公开。 必填项已用*标注