By gyakkun
上一篇捣腾路由的先鸽着, 写点有意思的。
打开一个bash, 敲dc -e 11533144122526433426838417720292223103708995620728433930P
就可以找到我的联系方式了, 很神奇吧(笑)。
这里面有点小故事, 实现方法也不难。
今天U2例行签到, 见到了一个失效的头像URL, 顺手看了下主域名, 发现有点面善atr.me
。视奸了一会儿之后终于确定就是bgm网友AstroProfundis的博客… 好吧并不意外, 毕竟华语核心观众的圈子相当小。
看了一会儿博客,找到了atr菊苣进入阿里的伯乐骨头, 又视奸了一下, 发现他的联系方式很有意思
联系方式:
gtalk,执行以下代码可得:
dc -e 561966095130892579929141297432895687762711112970P
具体是什么大家敲一敲就知道了… 但这样的加密方式很炫酷好吗!比base64之流高到不知哪里去了(笑)
这个DC命令什么来头? 一查才知道是上古unix工具之一, 本职是计算逆波兰表达式, 又衍生出一系列的语法, 和三剑客sed/grep/awk一样有着自成一套的控制指令, 说是一种脚本也不为过。
dc -e
接受一个dc script作为输入, 结尾的P是输出栈顶元素的意思, 输出的结果可能是字符串或是数字。
//man dc
P Command
Otherwise it is a number, and the integer portion of its absolute value is printed out as a "base (UCHAR_MAX+1)" byte stream.
Strings
All registers and the stack can hold strings, and dc always knows whether any given object is a string or a number.
也就是说, dc维护着一个栈, 当通过P输出栈顶的时候, 栈顶元素可以被当成8位字节流输出。
打开ASCII表, 尝试dc -e 81P
, 输出果然是”A”。
接下来要做的事情便是把字符串转成字节流, 表示成二进制串, 再用二进制转十进制将其转成长整数。
举个栗子:
gyak -> g(0110 0111)
y(0111 1001)
a(0110 0001)
k(0110 1011)
-> 0110 0111 0111 1001 0110 0001 0110 1011 (bin)
-> 1736008043 (dec)
敲进终端试试
gyakkun@gyakkun-vm:~$ dc -e 1736008043P
gyakgyakkun@gyakkun-vm:~$
由于没有换行符, 所以gyak
和gyakkun@gyakkun-vm:~$
粘在了一起。
所以本质上, 我们需要做的是把字符串从内存中取出来, 然后用十进制表示。字符串->字节流->二进制数->十进制数, 难点在于字节流到二进制字符串的转换, 以及超长的二进制转十进制。
一个朴素的字符串元素转01字符串函数string2Bin如下(javascript):
function string2Bin(str) {
var result = [];
for (var i = 0; i < str.length; i++) {
// toString(Base), 二进制
result.push(str.charCodeAt(i).toString(2));
}
return result;
}
返回一个数组, 存储的是高有效位置存在低地址(小端序)的01字符串, 和正常的认知习惯一致(小端序万岁(笑))
> string2Bin("gyak")
> (4) ["1100111", "1111001", "1100001", "1101011"]
发现并没有补齐8位, 取一个补齐函数
function pad(num, n) {
var len = num.toString().length;
while(len < n) {
num = "0" + num;
len++;
}
return num;
}
加在for循环后面, 并简单reduce即得到整合的01串
function string2Bin(str) {
var result = [];
var strArr = [];
for (var i = 0; i < str.length; i++) {
result.push(str.charCodeAt(i).toString(2));
}
result.forEach(function(curVal, idx, arr){
var num = parseInt(curVal);
strArr.push(pad(num,8))
})
var final = strArr.reduce(function(x,y){
return x+y;
})
return final;
}
至于超长的二进制转十进制… 原生js应该是无力了, 找了段11年前的代码 (https://bbs.pediy.com/thread-56002.htm)
#include
#include
#define MAX_LEN 10000
typedef struct{
int len;
char value[MAX_LEN];
} TBigInt, *pBigInt;
void AddBit(pBigInt s,char BitValue){ //加一位, 0或者1。
int i;
for (i=0;ilen;i++)
s->value[i]*=2;
s->value[0]+=BitValue;
for (i=0;ilen;i++){
s->value[i+1]+=s->value[i]/10;
s->value[i]%=10;
}
if (s->value[s->len]) s->len++;
}
void OutputBigInt(pBigInt s){ //输出大整数类型
int i;
if (s->len==0){
puts("0");
} else {
for (i=s->len-1;i>=0;i--)
putchar(s->value[i]+'0');
putchar('\n');
}
}
int main(){
static char buf[1000000];
static TBigInt BigInt;
while (scanf("%s",buf)!=EOF){
memset(&BigInt,0,sizeof BigInt);
int i;
for (i=0;buf[i];i++)
AddBit(&BigInt,buf[i]=='1'?1:0);
OutputBigInt(&BigInt);
}
return 0;
}
现在大功告成了。最后给一个python一行解决方案 [允悲]
dc -e 119478888636517259055612461521120705176651269182846473956513706195861203318266031963052663857590454411930259941938858428322656289858423108577680485174083166511734620065184747508449486602P