2023HWS_RE复现

参考wp:https://oacia.cc/hws-2023/

Android

参考这篇文章:https://www.52pojie.cn/thread-1680984-1-1.html

360加固去掉





利用gg修改器+lua脚本去掉360加固后

然后就ok了,但是dex文件直接丢尽jadx会报错





把多余的数据删了就行



然后可以正常看



到so里面看,sm4加密,

enc给出,key,iv通过app里面的字符串猜出



Animals

有很多花指令



手动patch后发现还有一堆

脚本去花

import idc
def clear_junk(ea_start,ea_end):
junk=[0x74, 0x15, 0x75, 0x13, 0x8D, 0x44, 0x24, 0xFC, 0x83, 0xF0,
0x22, 0x3B, 0x04, 0x24, 0x74, 0x0A, 0xE8, 0x1F, 0x00, 0x00,
0x00, 0x74, 0x04]
while ea_start<ea_end:
if idc.get_bytes(ea_start,len(junk))==bytes(junk):
for i in range(len(junk)):
idc.patch_byte(ea_start+i,0x90)
ea_start+=len(junk)
ea_start+=1
ea_start=0x0000000000400800
ea_end=0x00000406E20
clear_junk(ea_start,ea_end)
print("ok")



修改junk里面的机器码,再进行去花

import idc
def clear_junk(ea_start,ea_end):
junk=[0x74, 0x0A, 0x75, 0x08, 0xE8, 0x10, 0x00, 0x00, 0x00, 0xEB,
0x04, 0xE8, 0x48, 0x8D, 0xBD, 0x90, 0xFE, 0xFF, 0xFF]
while ea_start<ea_end:
if idc.get_bytes(ea_start,len(junk))==bytes(junk):
for i in range(len(junk)):
idc.patch_byte(ea_start+i,0x90)
ea_start+=len(junk)
ea_start+=1
ea_start=0x0000000000400800
ea_end=0x00000406E20
clear_junk(ea_start,ea_end)
print("ok")

还有一种,这本质上同一种花

import idc
def clear_junk(ea_start,ea_end):
junk=[0x74, 0x0A, 0x75, 0x08, 0xE8, 0x10, 0x00, 0x00, 0x00, 0xEB,
0x04, 0xE8]
while ea_start<ea_end:
if idc.get_bytes(ea_start,len(junk))==bytes(junk):
for i in range(len(junk)):
idc.patch_byte(ea_start+i,0x90)
ea_start+=len(junk)
ea_start+=1
ea_start=0x0000000000400800
ea_end=0x00000406E20
clear_junk(ea_start,ea_end)
print("ok")

去完差不多这个样子

去不透明谓词



找到汇编



给寄存器赋值为0



这样就去掉了



按照这个方法开始去

代码审计

完全去掉不透明谓词和花指令

int __cdecl main(int argc, const char **argv, const char **envp)
{
char *v3; // rdi
size_t v4; // rax
size_t v5; // rax
size_t v6; // rax
size_t v7; // rax
size_t v8; // rax
size_t v9; // rax
unsigned int v10; // eax
const char *v12; // [rsp+68h] [rbp-2C8h]
const char *v13; // [rsp+80h] [rbp-2B0h]
const char *v14; // [rsp+98h] [rbp-298h]
const char *v15; // [rsp+B0h] [rbp-280h]
const char *v16; // [rsp+C8h] [rbp-268h]
char *src; // [rsp+E0h] [rbp-250h]
int j; // [rsp+144h] [rbp-1ECh]
char v19[88]; // [rsp+148h] [rbp-1E8h] BYREF
char v20[24]; // [rsp+1A0h] [rbp-190h] BYREF
int v21; // [rsp+1B8h] [rbp-178h] BYREF
int i; // [rsp+1BCh] [rbp-174h]
char v23[256]; // [rsp+1C0h] [rbp-170h] BYREF
char *s; // [rsp+2C0h] [rbp-70h] BYREF
char *v25; // [rsp+2C8h] [rbp-68h]
char *v26; // [rsp+2D0h] [rbp-60h]
char *v27; // [rsp+2D8h] [rbp-58h]
char *v28; // [rsp+2E0h] [rbp-50h]
char *v29; // [rsp+2E8h] [rbp-48h]
pthread_t newthread[2]; // [rsp+2F0h] [rbp-40h] BYREF
int v31; // [rsp+300h] [rbp-30h]
int v32; // [rsp+304h] [rbp-2Ch] v32 = 0;
v31 = argc;
newthread[1] = (pthread_t)argv;
sub_405FF0(argc, argv, envp);
memset(&s, 0, 0x30uLL);
s = (_BYTE *)("0. cat" + 3);
v25 = (_BYTE *)("1. dog" + 3);
v26 = (_BYTE *)("2. fox" + 3);
v27 = (_BYTE *)("3. panda" + 3);
v28 = (_BYTE *)("4. dragon" + 3);
v29 = (_BYTE *)("5. monkey" + 3);
memset(v23, 0, sizeof(v23));
for ( i = 0; i < 9; ++i )
{
v21 = 0;
puts("Welcome Animal shop");
sub_400900();
v3 = "%d";
printf("Please input my favorite animal: ");
__isoc99_scanf("%d", &v21);
switch ( v21 )
{
case 0:
src = s;
v4 = strlen(s);
strncat(v23, src, v4);
break;
case 1:
v16 = v25;
v5 = strlen(v25);
strncat("%d", v16, v5);
break;
case 2:
v15 = v26;
v6 = strlen(v26);
strncat(v23, v15, v6);
break;
case 3:
v14 = v27;
v7 = strlen(v27);
strncat("%d", v14, v7);
break;
case 4:
v13 = v28;
v8 = strlen(v28);
strncat(v23, v13, v8);
break;
case 5:
LOBYTE(v3) = 0;
v12 = v29;
v9 = strlen(v29);
strncat(v3, v12, v9);
break;
default:
puts("Input Err.");
exit(0);
}
}
pthread_create(newthread, 0LL, start_routine, 0LL);
pthread_join(newthread[0], 0LL);
puts("done.");
sub_4009A0(v19);
v10 = strlen(v23);
sub_400B30(v19, v23, v10);
sub_4059A0(v19, v20);
for ( j = 0; j < 16; ++j )
{
if ( byte_608090[j] != v20[j] )
{
puts("Wrong.");
exit(0);
}
}
puts("Win! , flag is flag{md5(input)}");
return 0;
}



这里我用md5加密硬爆没出来,后面看其他师傅wp才知道md5的常数换位置了,由于全是数字限制小,直接开爆了。

我这里用脚本

from itertools import product
from subprocess import Popen, PIPE # 创建迭代器
char_set = "012345"
char_length = 9
all_combinations = product(char_set, repeat=char_length) # 遍历组合并发送给进程
for combination in all_combinations:
inp = "".join(combination)
p = Popen('./main', stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)
# 发送输入
for i in inp:
p.stdin.write(i.encode()+b'\n')
#print(i.encode())
p.stdin.close() # 接收输出
res = p.stdout.read()
print(res.decode('utf-8')) # 检查是否包含flag
if b'flag' in res:
with open('flag.txt', 'w+') as f:
f.write(inp)
print(inp)
break

E

下一个ida插件

https://www.52pojie.cn/thread-1684608-1-1.html,

下一个易语言,把易语言的静态库全提取sign

https://bbs.kanxue.com/thread-263254.htm



利用工具提取后

我这只选择了一个,没想到同目录下的全提取了



然后打开ida的目录的sig\pc



把名称加载在末尾



进ida先用e插件



识别出来一些,然后shift f5 ,



挨个导入

然后搜索字符wrong,定位逻辑



这边可以看到符号全恢复了



进行代码审计,发现我们输入的input分前后2部分进行

先进行转化操作

def en_head(y):
for i in range(len(y)):
y[i]<<=1
y[i]^=0xbf
y[i]>>=1
y[i]&=0xff
print(bytes(y).decode(),end='\n')
#后部分
def en_tail(y):
for i in range(len(y)):
y[i]>>=1
y[i]^=0x81
y[i]<<=1
y[i]&=0xff
print(bytes(y).decode(),end='\n')



这个就是检测数字,如果字符串是数字就进循环

进行调试

三方支持库命令((unsigned int)ecalc_fnUnlNumImportNum, 2, v69, 0, 131082, v67, 0, 0x80000301);

易语言存储结构研究

这里下一个易语言进行研究,主要导入eCalc的文件

导入教程: https://www.jb51.net/article/151735.htm

.版本 2
.支持库 eCalc .程序集 程序集1 .子程序 _启动子程序, 整数型
.局部变量 局_大数a, 大数
.局部变量 局_大数b, 大数
.局部变量 局_结果, 大数
.局部变量 局_显示, 文本型 局_大数a.导入数字 (287454020)
局_大数b.导入数字 (1432778632)
局_结果 = 局_大数a.加 (局_大数b)
局_显示 = 局_结果.导出文本 ()
标准输出 (, 局_显示)
返回 (0)



静态编译

三方支持库命令((unsigned int)ecalc_fnUnlNumImportNum, 2, v7, 0, 131082, 0x11223344, 0, -2147482879);

这很明显时让v7=0x11223344

此时v7为一个指针



跟进



继续跟进



继续跟进



此时不难看到我们的数据

经过多次探索得到它的数据结构



后面存放的是链表,每4个字节存放高位信息

val=val_head*(10**9)+val

然后用此方法探索乘,减,=



最终完整的算法

flag后半部分算法

for i in range(1,901):
input_tail=input_tail-i*0x70955fc45*i+i*0x34ED1CCB+0xD1558
if input_tail==0:
break

flag上半部分同理可得

for i in range(1,801):
input_tail=input_tail-i*0x70955fc45*i+i*0x34ED1CCB+0xD1558
if input_tail==0:
break

我们exp

import string
x=string.ascii_letters+string.digits
table=[ord(i) for i in x]
def re_num(number):
x=0
for i in range(1,number):
x=x+i*0x70955fc45*i+i*0x34ED1CCB+0xD1558
return x
def re_tail(y):
for i in range(len(y)):
for j in table:
x=j
j<<=1
j^=0x81
j>>=1
j&=0xff
if j==y[i]:
print(chr(x),end='')
def re_head(y):
for i in range(len(y)):
for j in table:
x=j
j<<=1
j^=0xbf
j>>=1
j&=0xff
if j==y[i]:
print(chr(x),end='') input_head=[ord(i) for i in str(re_num(801))]
input_tail=[ord(i) for i in str(re_num(901))]
re_head(input_head)
re_tail(input_tail)

2023HWS_RE复现的更多相关文章

  1. C++复现经典游戏——扫雷

    国庆小长假,当大家都去看人山人海的时候,我独自一人狂码代码.这两天想要实现的内容是Windows上的一个经典游戏——扫雷.相信90后和一些上班族对此并不陌生.然而,从win8开始,扫雷就不再是Wind ...

  2. [troubleshoot][archlinux][X] plasma(KDE) 窗口滚动刷新冻结(约延迟10s)(已解决,root cause不明,无法再次复现)

    现象: konsole,setting等plasma的系统应用反应缓慢,在滚动条滚动时,尤为明显. 触发条件: 并不是十分明确的系统滚动升级(Syu)后,产生. 现象收集: 可疑的dmesg [ :: ...

  3. 时空上下文视觉跟踪(STC)算法的解读与代码复现(转)

    时空上下文视觉跟踪(STC)算法的解读与代码复现 zouxy09@qq.com http://blog.csdn.net/zouxy09 本博文主要是关注一篇视觉跟踪的论文.这篇论文是Kaihua Z ...

  4. ShadowBroker释放的NSA工具中Esteemaudit漏洞复现过程

    没有时间测试呢,朋友们都成功复现,放上网盘地址:https://github.com/x0rz/EQGRP 近日臭名昭著的方程式组织工具包再次被公开,TheShadowBrokers在steemit. ...

  5. CVE-2017-8464远程命令执行漏洞(震网漏洞)复现

    前言 2017年6月13日,微软官方发布编号为CVE-2017-8464的漏洞公告,官方介绍Windows系统在解析快捷方式时存在远程执行任意代码的高危漏洞,黑客可以通过U盘.网络共享等途径触发漏洞, ...

  6. Samba远程代码执行漏洞(CVE-2017-7494)本地复现

    一.复现环境搭建 搭建Debian和kali两个虚拟机: 攻击机:kali (192.168.217.162): 靶机:debian (192.168.217.150). 二.Debian安装并配置s ...

  7. Office远程代码执行漏洞CVE-2017-0199复现

    在刚刚结束的BlackHat2017黑帽大会上,最佳客户端安全漏洞奖颁给了CVE-2017-0199漏洞,这个漏洞是Office系列办公软件中的一个逻辑漏洞,和常规的内存破坏型漏洞不同,这类漏洞无需复 ...

  8. Node.js CVE-2017-1484复现(详细步骤)

    0x00 前言 早上看Sec-news安全文摘的时候,发现腾讯安全应急响应中心发表了一篇文章,Node.js CVE-2017-14849 漏洞分析(https://security.tencent. ...

  9. 【S2-052】漏洞复现(CVE-2017-9805)

    一.漏洞描述 Struts2 的REST插件,如果带有XStream组件,那么在进行反序列化XML请求时,存在未对数据内容进行有效验证的安全隐患,可能发生远程命令执行. 二.受影响版本 Struts2 ...

  10. CVE-2017-8464复现 (远程快捷方式漏洞)

    我们的攻击机IP是192.168.222.133 目标机IP是192.168.222.132 我们首先生成一个powershell msfvenom -p windows/x64/meterprete ...

随机推荐

  1. 2022-11-23: 分数排名。输出结果和表的sql如下。请写出输出结果的sql语句? +-------+------+ | score | rank | +-------+------+ | 4.

    2022-11-23: 分数排名.输出结果和表的sql如下.请写出输出结果的sql语句? ±------±-----+ | score | rank | ±------±-----+ | 4.00 | ...

  2. react 代码自动格式化

    咦写了几行代码发现保存后没有被格式化? import React from "react"; import {Row,Col } from "antd"; ex ...

  3. nginx发布vue 项目

    在本次使用nginx发布vue项目遇到 配置location 始终404 和 在项目子目录点击浏览器刷新出现404问题 使用nginx发布vue项目,为了方便测试就下载了一个nginx 放置自己目录下 ...

  4. 代码随想录算法训练营Day35 贪心算法

    代码随想录算法训练营 代码随想录算法训练营Day35 贪心算法| 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球 860.柠檬水找零 题目链接:860.柠檬水找零 在柠 ...

  5. 代码随想录算法训练营Day11 栈与队列|20. 有效的括号  1047. 删除字符串中的所有相邻重复项  150. 逆波兰表达式求值

    20.有效的括号 题目链接:20.有效的括号 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合 ...

  6. python 学习 ---函数(带参数)

    函数式编程最重要的是增强代码的重用性和可读性 1 def 函数名(参数): 2 3 ... 4 函数体 5 ... 函数的定义主要有如下要点: def:表示函数的关键字 函数名:函数的名称,日后根据函 ...

  7. Google Chrome 超详细使用教程

    由于微信不允许外部链接,你需要点击文章尾部左下角的 "阅读原文",才能访问文中的链接. 调查统计机构 NetMarketShare 发布最新的 7 月份报告,在全球浏览器市场,谷歌 ...

  8. Win32 GUI 汇编

    获取句柄 API函数 GetModuleHandle 取模块句柄,lpModuleName 是一个指向模块名称字符串的指针,使用 NULL 获取当前程序句柄. invoke GetModuleHand ...

  9. Apikit 自学日记:如何安装 Apikit

    肯定会有和我一样的小白,第一次听说 Apikit这个工具,那么我今天和大家一起学习下这个工具如何安装. Apikit 有三种客户端,你可以依据自己的情况选择.三种客户端的数据是共用的,因此你可以随时切 ...

  10. 关于Abp Vnext 权限授权的问题

    一.问题 最近收到一位朋友的求助,说他项目上的权限授权出现了问题,现象是在基础服务授权角色:RC 权限:X.Default,在基础服务使用RC角色的用户登录能访问到权限X.Default资源,而在X服 ...