L-CTF 2016 Writeup ( Part III )

Misc

misc 150

首先,我们解压得到一个Misc150.txt文件。这里必须使用Winrar解压,因为其中存在文件流数据。这一点在txt文件以及压缩包大小不一致中也可以看得出来。Misc150.txt中说道 Flag.zip behind me. 暗示着文件流的存在,以及流名称为Flag.zip。我们就使用命令行来访问文件流。

>"C:\Program Files\WinRAR\winrar.exe" Misc150.txt:Flag.zip

打开压缩包,得到一个小压缩包一个图片。其中,小压缩包名字为Steins;Gate也就是命运石之门的名字。而图片的Christina则是命运石的女主角。在题目的描述中,有说道“命运石之门里没有flag”,这也就暗示着flag不在这两文件里面。这样我们剩下的选择就只有当前这个zip文件了。如果细心的话,会发现压缩包的注释部分有非常长条的空白行,将其三行复制出来,tab用1替换,空格用0替换就可以得到一串二进制。简单判断二进制应为7为ASCII码,解码得flag。

请输入图片描述

另一种方法是通过Ultra edit等软件,查看包数据也能发现问题。在这一部分有规律的0x090x20,将其提取出来,替换一下也能得到flag。

请输入图片描述

misc 300

拿到流量包,分析可知有两次wpa握手的过程,连接的同一个wifi。第二次握手过程中wireshark根据标志位识别出来的顺序颠倒了,说明握手包有问题。根据wpa认证过程,修改Key Information字段,得到修复的包。然后扔到aircrack去跑,在有hint的情况下三个小时之内能跑出来,得到密码:55672627,然后airdecap解包。本来以为不会有大佬注意到这是被打掉了强制重新连得,没想到大佬们注意到了好细心Orz。

请输入图片描述

tips:应该先爆破再修复和先修复再爆破是不一定的,aircrack如果不修复就爆破是爆破不出来的,有的工具是通过第一次认证破解的,有的工具通过第二次认证破解,如果不修复的话跑出来与否就看用的啥了,通过第二次认证跑的肯定不修复出不来结果。

总之最后得到通信内容:

  • 一个文件需要逆向分析:re2
  • 一个ip和端口:119.28.62.216:3333

re2源码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void readFlag()
{
    FILE *pFile=fopen("./flag.txt","r");
    char pBuf[32]={0};//socat tcp-l:8000,reuseaddr,fork exec:./re2
    fread(pBuf,1,32,pFile);
    printf("%s",pBuf);
    fclose(pFile);
}

int main()
{
    int i,j;
    int a[19*19] = {0};
    int b[19][19];
    int k;

    setvbuf(stdout, 0, 2, 0);
    setvbuf(stdin, 0, 2, 0);

    for (k = 1; k <=19 ; k=k+2)
    {
        for (i = 0; i < k; ++i)
        {
            for (j = 0; j < k; ++j)
            {
                scanf("%d",&b[i][j]);
                a[(b[i][j]-1)%(k*k)] = 1;
            }
        }

        for (i = 0; i < k*k; ++i)
        {
            if(a[i]==0)
                return -1;
        }

        int num;
        srand(time(NULL));
        num = rand()%k;

        int c1=0,c2=0,c3=0,c4=0;
        for (i = 0; i < k; ++i)
        {
            c1 += b[num][i];
        }
        for (i = 0; i < k; ++i)
        {
            c2 += b[i][num];
        }
        for (i = 0; i < k; ++i)
        {
            for (j = 0; j < k; ++j)
            {
                if(i==j) c3 += b[i][j];
                if (i+j==k-1) c4+=b[i][j];
            }
        }
        if (c1 != c2 || c3 != c4 || c1 != c3)
            return -1;
    }

    readFlag();

    return 0;
}

编写程序并提交结果:

#include  <stdio.h>
#include  <stdlib.h>

#define   MAXSIZE   20

int main()
{
     int  matrix[MAXSIZE][MAXSIZE]; /* the magic square   */
     int  count;                    /* 1..n*n counting    */
     int  row;                      /* row index          */
     int  column;                   /* column index       */
     int  order;                    /* input order        */
     char line[100];

     for (order = 1; order <= 19; order += 2)
     {
          row    = 0;         /* start of from the middle */
          column = order/2;   /* of the first row.        */
          for (count = 1; count <= order*order; count++) {
               matrix[row][column] = count; /* put next # */
               if (count % order == 0)  /* move down ?    */
                    row++;    /* YES, move down one row   */
               else {         /* compute next indices     */
                    row    = (row == 0) ? order - 1 : row - 1;
                    column = (column == order-1) ? 0 : column + 1;
               }
          }
          for (row = 0; row < order; row++) {
               for (column = 0; column < order; column++)
                    printf("%d ", matrix[row][column]);
          }
          printf("\n");
     }
     return 0;
}

misc 400

扫端口和ftp登陆尝试的流量都没啥用。。。

利用proftp的洞:CVE2015-3306,获得了192.168.138.136的shell,写到web目录下一个1.php一句话。然后通过另外一台机器连菜刀,down下来了两个文件:xor.jpg和whoami.jpg。名字提示很明显,xor,没有挖坑,所以两个文件xor一下得到可运行的python代码,逆向这段代码可获得AES_KEY{}。话说为什么会有人提交这个东西呢……明显格式不对啊……

proftpd漏洞利用流量:

请输入图片描述

然后取得msfshell:

请输入图片描述

利用msfshell写菜刀一句话:

请输入图片描述

菜刀连接下载文件,菜刀流量的话,去掉文件头和文件尾的东西就ok了:

请输入图片描述

图片解密python脚本:

with open("whoami.jpg",'r') as file:
  pic=file.read()
temp=''
with open('xor.jpg','r') as file:
  t=file.read()
  for a,b in zip(t,pic):
    print chr(ord(a)^ord(b)),

m="cc90b9054ca67557813694276ab54c67aa93092ec87dd7b539"
def process(a,b,m):
  return "".join(map(chr,map(lambda x: (x*a+b)%251,map(ord,m.decode('hex')))))
for i in xrange(255):
  for j in xrange(255):
    if "AES" in process(i,j,m):
      print process(i,j,m)

得到AES_key{},AES啊!不是LCTF!

然后DNS流量异常,找了个DNSshell不能用啊,于是自己xjb写了一个xjb传的shell。发一个baidu.com的开始接收命令,一个命令执行传回去一个google.com。找到这些返回google.com的蜜汁流量,拼到一起用AES_key解密就可以看到:

请输入图片描述

混进去了一堆xjb访问的http流量,访问了L-team.org的about页面,发现DNS解析了不少dalao博客的地址,就当广告了233333:

请输入图片描述

最后,解密得到Please submit the used ftp CVE ID like "CVE********"and LCTF{A11_1n_0ne_Pcap} as your flag.eg."CVE12345678A11_1n_0ne_Pcap"

Reverse

Re100

re100设计之初就是消耗耐心的逆向,并没有什么有趣的东西在里面,所以最后的排序函数也只是烂代码增加难度系列(不要打我)。此外Re100最后的排序算法出了一点小问题,需要选手用暴力搜索来解出这道题,不过对题目整体设计没有影响。

算法主体是CBC+字符串排序。外围是Qt的信号槽机制。

排序函数:

    for(QVector<int>::iterator iter = pd.begin(); iter != pd.end(); ++iter){
        num = *iter;

        num = num % key.size();

        while(randlist.indexOf(num) != -1){
            num = (num + 1) % pd.size();
        }

        randlist.append(num);
    }

    void Randlist::randpd(QVector<int> &pd){
        int idlist;
        int begin_index = 0;
        int idpd = begin_index;
    
        do{
            idlist = randlist.indexOf(idpd);
            std::swap(pd[idlist], pd[begin_index]);
            idpd = idlist;
        }while(idpd != begin_index);
    }

程序流程是,获取输入后先用\x09补全长度到5的倍数。之后是CBC加密,这里没有使用初始IV。key="Cirno",5个字符一组,先和将每一个字符的高4位和低4位交换,再和key异或。除第一组外每组再和前一组异或。最后使用上面的代码和最初(补全后)的输入生成奇怪的位置字典,重排CBC后的字串,进行strcmp

Re200

re200是一个完(zhi)整(zhang)的文件加密器。当然,解密器我没有写。这题本来是想玩SMC的...但是后来发现写好的SMC对逆向无任何干扰,反而是signal坑了不少人。

程序在main函数执行前(init)先运行了sub_8048901,用sig == ppid检测了是否被调试,如果是的话就直接将一个后面用到的表填充为错误数值。之后是取得分页大小,将sub_8048AC3所在的内存设置为RWX。最后设置signal(SIGUSR1, sub_80489FB)。以上这些除了sysconf(),都是int 0x80实现的。

main函数执行,再一次检测是否有调试(有的话直接exit),获得用户输入,补全为偶数长度,拷贝字符串到全局变量,然后用kill(0, SIGUSR1)触发了之前设置的signal,跳转到sub_80489FB。将补全后的字符串分为两个一组,循环调用sub_8048A7B。在sub_8048A7B中根据((a>>2)&0x3)和之前的表得到一个函数地址,调用sub_8048AC3

sub_8048AC3在初始化时被设置为RWX...利用sub_8048A7B中的函数地址进行SMC,跳转到取得的函数中。在之后的函数就是对这组字符的移位和异或加密。

signal处理完成,回到正常流程中,再再一次检测是否有调试(出题人:求不打)。对加密完的字串做base16。最后用维吉尼亚算法加密文件,输出。

解题时,维吉尼亚直接在线解密就可以,然后得到key.明文是小说《基督山伯爵》里面随意选的一段话,只是为了帮助进行维吉尼亚解密,并没有实际意义。解密得到key后,程序就和一个crackme没什么区别了...分析算法逆出orignal key即可。测试时是正向暴力破解,反推也没问题。

orignal key = H4ck1ngT0TheGate

此外:

  • main函数的前后分别会执行init和finit。本题源码中的init声明如下
void init_game(void) __attribute__((constructor));
  • objdump和gdb分析ELF时都需要Section header table,但是ELF文件的执行只需要Program header table。程序编译完之后直接覆盖了Section header table,导致gdb直接GG。但是对IDA无效。section header table也是可以重建的,但是...之后还是有反调试拦着(逃)。
  • 因为char类型的符号问题,在逆推时会有点小问题。但是这并不重要...逆推也是可解的。

测试脚本:

    char *strkey = "ieedcpgdhkedddfenkfaifgggcgbbbgf";
    
    char all_a;
    char all_b;
    
    int main(int argc, char const *argv[])
    {
        boom();
        return 0;
    }
    
    void zero(){
        char c;
        //c = a
        c = (all_a & 0xF0) | (all_b & 0x0F);
        all_b = (all_a & 0x0F) | (all_b & 0xF0);
        all_a = c;
    
        all_a = all_a ^ 0x99;
        all_b = all_b ^ 0x55;
    }
    
    void one(){
        all_a = all_a ^ all_b;
        all_b = ((all_b >> 4) & 0x0F) | ((all_b << 4) & 0xF0);
    }
    
    void two(){
        //c = a
        char c;
        c = (all_a & 0x0F) | (((all_b & 0x0F) << 4) & 0xF0);
        all_b = ((all_a >> 4) & 0x0F) | (all_b & 0xF0);
        all_a = c;
    }
    
    void three(){
        //and 0xF0 ?
        all_a = all_a ^ (all_a << 4);
        all_b = all_b ^ (all_b << 4);
    }
    
    void boom(){
        char end[16];
        int map; 
        int a, b, i;
    
        char tmp_1, tmp_2;
        char end_1, end_2, end_3, end_4;
    
        for(i = 0; i < 32; i+=4){
            printf("Num %d and %d:\n", i, i+1);
            for(a = 0; a <= 0xFF; ++a){
                for(b = 0; b <= 0xFF; ++b){
                    all_a = a;
                    all_b = b;
        
                    map = (a >> 2) & 0x3;
        
                    switch(map){
                        case 0: zero();break;
                        case 1: one();break;
                        case 2: two();break;
                        case 3: three();break;
                    }
        
                    tmp_1 = all_a;
                    tmp_2 = all_b;
    
                    end_1 = (tmp_1 & 0x0F) + 0x61;
                    end_2 = ((tmp_1 >> 4) & 0x0F) + 0x61;
                    end_3 = (tmp_2 & 0x0F) + 0x61;
                    end_4 = ((tmp_2 >> 4) & 0x0F) + 0x61;
    
                    if((end_1 == strkey[i]) && (end_2 == strkey[i+1]) && (end_3 == strkey[i+2]) && (end_4 == strkey[i+3])){
                        printf("%c%c\n", a, b);
                    }    
                }
            }
        }
    }

Re300

Re300原本的出题人跑路了,我临时帮他出题。随手找了个DDoS木马。本着不互相伤害的原则。没有用MIPS版本,没有去掉符号表。所以就很easy了。

首先,题目提供一个ELF可执行文件(re300)和抓的包(dump.pcap)。提示信息flag(ip:port),那自然是找被打的ip和端口号了。关于此马的详细分析可参考 https://www.sans.org/reading-room/whitepapers/malicious/analyzing-backdoor-bot-mips-platform-35902R_y_RQ 因为使用AES加密数据包,遂家族命名为AES.DDoS。本样本产自China的变种台风ddos,支持多平台MIPS,Windows,Linux等。

首先观察数据包,就那么几条。显然C&C IP为192.168.168.133,上线端口48080,而Victim IP 为192.168.168.148(由第4个数据包可以确定)。那么可以确定第16个数据包,为中控IP像肉鸡发送的指令包。

Re 300

懂得人自然懂。数据包的格式一般为【指令号+数据内容】在_ConnectServerA函数里,106行接收buffer,前4个字节表示指令号,当其为6时(118行),执行DealwithDDoS:

Re 300

ok,接下来我们可以发现程序使用AES算法开始解密,同时注意到数据包中存在重复的数据7df76b0c1ab899b33e42f047b91b546f,很容易联想到分组加密的ECB(电码本)模式,并且分组长度是16,这点从key0也可以辅证。

Re 300

由此我们可以解密出数据包。接下来就是找到数据包中表示ip和port的字段。这个看一下DealwithDDoS(128行)这个函数。数据包的偏移位置0x184表示attackMode(SYN,TCP,UDP...),那0x188处就是轮数了吧。

Re 300

随便挑一个mode跟进,SYN_Flood函数。40行和41行分别取出port,ip。至此,题目想要的数据已经分析出来了。

Re 300

最后就是写脚本啦:

from Crypto.Cipher import AES
from struct import unpack
from hashlib import md5

with open('./re300') as fp:
    fp.seek(0xe81ff)
    key = fp.read(16)

with open('./dump.pcap') as fp:
    data = fp.read()
    idex = data.find('\x06\x00\x00\x00')
    data = data[idex+4:idex+0x1a4]

aes  = AES.new(key , AES.MODE_ECB)
text = aes.decrypt(data)
ip   = text[:text.find('\x00')]
port = unpack('<H',text[0x1d4-0x54:][:2])[0]

flag = md5(ip+':'+str(port)).hexdigest()
print 'flag is: {0}'.format(flag)

Re 400

题目试图用magic_file作为块链数据挖矿,挖到前3400个block之后,用他们的哈希值生成IV和Key,解密Flag字符串。题目除了去除了符号表之外,没有任何反调试和反分析内容,基本就是考察算法逆向能力。题目的一个切入点就是,通过trace可以发现在一系列函数中耗了很长时间,由此可以发现SHA256的相关代码,再分析上下文的代码,也就差不多能看出挖矿的过程了。结合题目前期给出的UID(转换成十进制搜索,可以发现是第一个block的Nonce值),以及后期给出的Bitcoin提示,应该是能明白程序在干什么的。

相关代码已经上传到Github了,这里就不多介绍。

Re 500

关于Re500,首先向大家道歉,由于时间关系,出题人手残把SIU_PGPDOSIU_PGPDI的地址值写反了,比赛结束后有队伍报告了这个问题……

这道题是一个跑在嵌入式设备中的程序,目标芯片是Freescale的MPC5674F,使用了Erika RTOS。程序原理是,初始化外部的LCD1602,并将flag打印到屏幕上。在设计的时候,我埋下的几个坑点有:

  • 有时候IDA导入时,默认开了VLE,你要自己在导入成功之后去Options里关掉VLE,然后Reanalyze一下(导入的时候关掉VLE是没作用的,不知道是我的使用方法不对还是他自己的bug,有知道的还望指点下)。这个在题目描述里实际也是有的("I Hate Change",VLE是变长指令集);
    Disable VLE
  • 无意把寄存器写反,坑了一波……这个真不是有意的……再次向表哥们低头;
  • 有的队伍看到ELF就先去用qemu跑了,这个应该是跑不起来的……用TRACE32应该可以搞,不过未必比静态分析方便;
  • 程序是跑在一个RTOS上的,所以如何把RTOS的代码和业务代码分开,对没有过相关开发或逆向经验的选手可能有点麻烦(不过也完全可以借助FLIRT);
  • MCU和外设(LCD1602)的连线采用并行方式,但是D0-D7不是顺序接入的,有三根线被人为调换了位置,意在模拟由于PCB布线或生产问题,导致两个设备之间没办法用连续的一段IO口通信;
  • 没有直接向LCD1602送出字符,而是先把字模写到了CGRAM,然后再显示到屏幕上,另外字模的显示字符和对应字母是不一致的,而且先解出来IO口的乱序规则才可以使用字模……;
  • 有三段代码都能和LCD1602通信,但是仔细分析之后可以发现,只有一段代码比较像正确的代码,因为只有那段循环每次都有机会和外设通信,其他的是忽悠你的,毕竟连优先级都没有第一段高;

同样把代码传到了Github上,大家可以自行查阅。

拿到题后先正确的载入到IDA中,然后最简单的方法是直接查看字符串,有一段以FAIL开头的字符串,找到引用函数,然后直接去读。这种方法根本不需要对RTOS和业务代码做区分,比较快。通过向外发送的控制字,以及将数组取出分析,可以知道这应该是在送字模,但是字模是乱掉的。解决办法就是,要么自己根据FLAG格式推测,要么从送控制字之前的几个移位操作分析出硬件连线。

解题脚本如下:

#!/usr/bin/python

srctext="FAIL{tX1NJfGxnatFxY63Wxmlpxh12Z0h5xeGxaH56Nfy}" #get from bin

charmap={ # get charmap from bin
0xA9:[0x46, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x46], 
0xAA:[0x00, 0x00, 0x00, 0x15, 0x15, 0x46, 0x42, 0x42], 
0xAB:[0x00, 0x00, 0x00, 0x44, 0x03, 0x45, 0x03, 0x45], 
0xAC:[0x00, 0x00, 0x00, 0x47, 0x02, 0x44, 0x01, 0x47], 
0xAD:[0x00, 0x00, 0x00, 0x45, 0x03, 0x02, 0x02, 0x45], 
0xAE:[0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x46], 
0xAF:[0x53, 0x53, 0x53, 0x53, 0x15, 0x15, 0x15, 0x15], 
0xA0:[0x12, 0x02, 0x02, 0x46, 0x03, 0x03, 0x03, 0x46], 
0xA1:[0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x57], 
0xA8:[0x46, 0x11, 0x11, 0x40, 0x04, 0x02, 0x10, 0x57], 
0xF9:[0x00, 0x00, 0x00, 0x44, 0x03, 0x47, 0x02, 0x45], 
0xFA:[0x00, 0x00, 0x00, 0x56, 0x15, 0x15, 0x15, 0x15], 
0xFB:[0x46, 0x11, 0x11, 0x46, 0x11, 0x11, 0x11, 0x46], 
0xFC:[0x13, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x44], 
0xFD:[0x04, 0x00, 0x00, 0x06, 0x04, 0x04, 0x04, 0x46], 
0xFE:[0x46, 0x11, 0x01, 0x44, 0x01, 0x01, 0x11, 0x46], 
0xFF:[0x00, 0x00, 0x00, 0x53, 0x06, 0x02, 0x02, 0x16], 
0xF0:[0x56, 0x03, 0x03, 0x46, 0x02, 0x02, 0x02, 0x16], 
0xF1:[0x47, 0x11, 0x10, 0x06, 0x40, 0x01, 0x11, 0x56], 
0xF2:[0x46, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x46], 
0xF3:[0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x50, 0x16], 
0xF4:[0x00, 0x00, 0x00, 0x53, 0x03, 0x03, 0x03, 0x45], 
0xF5:[0x56, 0x03, 0x03, 0x46, 0x03, 0x03, 0x03, 0x56], 
0xF6:[0x56, 0x03, 0x03, 0x46, 0x42, 0x03, 0x03, 0x17], 
0xF7:[0x17, 0x03, 0x42, 0x06, 0x42, 0x42, 0x03, 0x17], 
0xE8:[0x57, 0x50, 0x40, 0x04, 0x04, 0x04, 0x04, 0x04], 
0xE9:[0x40, 0x00, 0x44, 0x40, 0x40, 0x40, 0x40, 0x16], 
0xEA:[0x53, 0x03, 0x07, 0x07, 0x43, 0x43, 0x03, 0x17], 
0xEB:[0x40, 0x44, 0x42, 0x42, 0x50, 0x47, 0x40, 0x41], 
0xEC:[0x04, 0x04, 0x44, 0x42, 0x42, 0x47, 0x03, 0x13], 
0xED:[0x00, 0x56, 0x03, 0x03, 0x03, 0x46, 0x02, 0x16], 
0xEE:[0x00, 0x00, 0x00, 0x47, 0x40, 0x04, 0x04, 0x47], 
0xEF:[0x45, 0x03, 0x10, 0x10, 0x51, 0x11, 0x03, 0x44], 
0xE0:[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57], 
0xE1:[0x56, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x56], 
0xE2:[0x57, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x57], 
0xD9:[0x47, 0x11, 0x10, 0x10, 0x10, 0x10, 0x11, 0x46], 
0xDA:[0x12, 0x02, 0x02, 0x43, 0x42, 0x46, 0x03, 0x17], 
0xDB:[0x00, 0x00, 0x00, 0x44, 0x03, 0x03, 0x03, 0x44], 
0xDC:[0x13, 0x03, 0x03, 0x47, 0x03, 0x03, 0x03, 0x13], 
0xDD:[0x13, 0x03, 0x03, 0x42, 0x42, 0x44, 0x04, 0x04], 
0xDE:[0x16, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x57], 
0xDF:[0x57, 0x10, 0x10, 0x56, 0x01, 0x01, 0x11, 0x46], 
0xD0:[0x00, 0x00, 0x00, 0x53, 0x42, 0x04, 0x42, 0x53], 
0xD1:[0x57, 0x15, 0x04, 0x04, 0x04, 0x04, 0x04, 0x46], 
0xD2:[0x12, 0x02, 0x02, 0x46, 0x03, 0x03, 0x03, 0x17], 
0xD3:[0x53, 0x42, 0x42, 0x04, 0x04, 0x04, 0x04, 0x46], 
0xD4:[0x57, 0x03, 0x42, 0x46, 0x42, 0x02, 0x02, 0x16], 
0xD5:[0x46, 0x11, 0x11, 0x11, 0x47, 0x01, 0x03, 0x46], 
0xD6:[0x00, 0x04, 0x04, 0x46, 0x04, 0x04, 0x04, 0x41], 
0xD7:[0x46, 0x50, 0x10, 0x56, 0x11, 0x11, 0x11, 0x46], 
0xC8:[0x00, 0x45, 0x03, 0x03, 0x03, 0x45, 0x01, 0x41], 
0xC9:[0x00, 0x17, 0x03, 0x42, 0x44, 0x04, 0x04, 0x12], 
0xCA:[0x46, 0x11, 0x11, 0x11, 0x17, 0x51, 0x46, 0x41], 
0xCB:[0x00, 0x00, 0x00, 0x17, 0x03, 0x42, 0x44, 0x04], 
0xCC:[0x53, 0x42, 0x42, 0x04, 0x04, 0x42, 0x42, 0x53], 
0xCD:[0x57, 0x50, 0x40, 0x04, 0x04, 0x02, 0x03, 0x57], 
0xCE:[0x15, 0x15, 0x15, 0x46, 0x42, 0x42, 0x42, 0x42], 
0xCF:[0x00, 0x45, 0x03, 0x44, 0x02, 0x47, 0x02, 0x45], 
0xC0:[0x00, 0x00, 0x00, 0x56, 0x03, 0x03, 0x03, 0x17], 
0xC1:[0x41, 0x04, 0x04, 0x47, 0x04, 0x04, 0x04, 0x47], 
0xC2:[0x57, 0x03, 0x42, 0x46, 0x42, 0x02, 0x03, 0x57], 
0xC7:[0x41, 0x01, 0x01, 0x45, 0x03, 0x03, 0x03, 0x45], 
0xE3:[0x41, 0x40, 0x40, 0x04, 0x40, 0x40, 0x40, 0x41], 
0xE5:[0x06, 0x04, 0x04, 0x40, 0x04, 0x04, 0x04, 0x06]
}
for i in srctext:
    c = list(charmap[0x98^ord(i)])
    c = [0]*(8-len(c))+c
    for r in c:
        if type(r)==str:
            r = ord(r)
        # swap the io line
        r=((r&0b00000001))        |((r&0b00000010)<<2)        |((r&0b00000100))        |((r&0b00001000)>>3)        |((r&0b00010000))        |((r&0b00100000))        |((r&0b01000000)>>5)        |((r&0b10000000))
        # convert to graph
        r = bin(r)[2:]
        r = '0'*(8-len(r))+r
        r = r.replace('0',' ')
        r = r.replace('1','\x18')
        print(r)
    input()

Attachments

  1. Pwn出题人给出的源码
  2. Re400、500的源码
tagged by none  

Comment Closed.

© 2014 ::L Team::