WinMain函数参数介绍

int WINAPI WinMain(

HINSTANCE hInstance, // handle to current instance

HINSTANCE hPrevInstance, // handle to previous instance

LPSTR lpCmdLine, // command line

int nCmdShow // show state

);

WinMain函数接收4个参数,这些参数都是在系统调用WinMain函数时,传递给应用程序的。

第一个参数hInstance表示该程序当前运行的实例的句柄,这是一个数值。当程序在Windows下运行时,它唯一标识运行中的实例(注意,只有运行中的程序实例,才有实例句柄)。一个应用程序可以运行多个实例,每运行一个实例,系统都会给该实例分配一个句柄值,并通过hInstance参数传递给WinMain函数。

第二个参数hPrevInstance表示当前实例的前一个实例的句柄。通过查看MSDN我们可以知道,在Win32环境下,这个参数总是NULL,即在Win32环境下,这个参数不再起作用。

第三个参数lpCmdLine是一个以空终止的字符串,指定传递给应用程序的命令行参数。例如:在D盘下有一个sunxin.txt文件,当我们用鼠标双击这个文件时将启动记事本程序(notepad.exe),此时系统会将D:\sunxin.txt作为命令行参数传递给记事本程序的WinMain函数,记事本程序在得到这个文件的全路径名后,就在窗口中显示该文件的内容。要在VC++开发环境中向应用程序传递参数,可以单击菜单【Project】→【Settings】,选择“Debug”选项卡,在“Program arguments”编辑框中输入你想传递给应用程序的参数。

第四个参数nCmdShow指定程序的窗口应该如何显示,例如最大化、最小化、隐藏等。这个参数的值由该程序的调用者所指定,应用程序通常不需要去理会这个参数的值。

解题

首先对WinMain进行分析

查看DialogFunc参数

BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
const char *v4; // esi
const char *v5; // edi
int v7[11]; // [esp+8h] [ebp-20030h]
CHAR String[9]; // [esp+34h] [ebp-20004h]
CHAR v9[3]; // [esp+10034h] [ebp-10004h] if ( a2 == 272 )
return 1;
if ( a2 != 273 )
return 0; //
// a2 = 273
if ( a3 == 1001 ) // a3 = 1001
{
memset(String, 0, 0xFFFFu); // 给string清零
GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);// 获取对话框文本,然后赋值给string
if ( strlen(String) == 8 ) // string的长度要为8
{
v7[0] = 90;
v7[1] = 74;
v7[2] = 83;
v7[3] = 69;
v7[4] = 67;
v7[5] = 97;
v7[6] = 78;
v7[7] = 72;
v7[8] = 51;
v7[9] = 110;
v7[10] = 103;
sub_4010F0(v7, 0, 10); // 对v7进行处理,处理后的数据
// 51 67 69 72 74 78 83 90 97 103 110
memset(v9, 0, 0xFFFFu); // 给v16清零
v9[0] = String[5];
v9[2] = String[7];
v9[1] = String[6];
v4 = sub_401000(v9, strlen(v9)); // 对v9进行base64加密然后传递给v4
memset(v9, 0, 0xFFFFu); // 给v9清零
v9[1] = String[3];
v9[0] = String[2];
v9[2] = String[4];
v5 = sub_401000(v9, strlen(v9)); // 对v9进行base64加密然后传递给v4
if ( String[0] == v7[0] + 34 // string[0] = 'U'
&& String[1] == v7[4] // string[1] = 'J'
&& 4 * String[2] - 141 == 3 * v7[2] // string[2] = 'W'
&& String[3] / 4 == 2 * (v7[7] / 9) // string[3] = 'P'
&& !strcmp(v4, "ak1w") // v4 = "ak1w"
&& !strcmp(
v5, // v5 = "V1Ax"
"V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}
}
return 0;
}
if ( a3 != 1 && a3 != 2 )
return 0;
EndDialog(hDlg, a3);
return 1;
}

其中sub_4010F0函数参数已知,可以直接求出其处理结果

转换为C语言脚本

#include<bits/stdc++.h>

using namespace std;

// a1 为  v7对应地址
// a2 = 0
// a3 = 10
int __cdecl sub_4010F0(int *a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx result = a3; // result = 10
for ( i = a2; i <= a3; a2 = i ) // i=0;i<=10;a2=i
{
v5 = i;
v6 = a1[i]; // 遍历a1对应地址的元素
if ( a2 < result && i < result ) // a2<10 并且 i<10
{
do
{
if ( v6 > a1[result] ) // 如果a1[i] > a1[result]
{
if ( i >= result )
break; // 如果i>=result则退出循环
++i; // 给i+1
a1[v5] = a1[result]; // 让a1[1] = a1[result]
if ( i >= result )
break; // 如果i>=result则退出循环 重复
while ( a1[i] <= v6 ) // 当a1[i] <= v6 此循环一定成立
{
if ( ++i >= result ) // 如果i = result - 1
goto LABEL_13;
}
if ( i >= result )
break;
v5 = i;
a1[result] = a1[i];
}
--result; // result减一
}
while ( i < result );
}
LABEL_13:
a1[result] = v6; // 让a1[result] = 之前的a1[i]
sub_4010F0(a1, a2, i - 1); // 进行递归……
result = a3;
++i;
}
return result;
} int main()
{
int v7[11]={90,74,83,69,67,97,78,72,51,110,103};
sub_4010F0(v7,0,10);
for(int i=0;i<11;i++)
{
printf("%c ", v7[i]);
}
return 0;
}

得到如下结果

3 C E H J N S Z a g n
// a1 为  v7对应地址
// a2 = 0
// a3 = 10
int __cdecl sub_4010F0(int *a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx result = a3; // result = 10
for ( i = a2; i <= a3; a2 = i ) // i=0;i<=10;a2=i
{
v5 = i;
v6 = a1[i]; // 遍历a1对应地址的元素
if ( a2 < result && i < result ) // a2<10 并且 i<10
{
do
{
if ( v6 > a1[result] ) // 如果a1[i] > a1[result]
{
if ( i >= result )
break; // 如果i>=result则退出循环
++i; // 给i+1
a1[v5] = a1[result]; // 让a1[1] = a1[result]
if ( i >= result )
break; // 如果i>=result则退出循环 重复
while ( a1[i] <= v6 ) // 当a1[i] <= v6 此循环一定成立
{
if ( ++i >= result ) // 如果i = result - 1
goto LABEL_13;
}
if ( i >= result )
break;
v5 = i;
a1[result] = a1[i];
}
--result; // result减一
}
while ( i < result );
}
LABEL_13:
a1[result] = v6; // 让a1[result] = 之前的a1[i]
sub_4010F0(a1, a2, i - 1); // 进行递归……
result = a3;
++i;
}
return result;
}

对两个比较的字符串分别进行base64解密(byte内有明显的base64加密提示)

开头两个字符分别对应的是'3'+34后的字'U',和对应栈内v7[4]='J'

得到

UJWP1jMp

BUU-RE-刮开有奖-WinMain的更多相关文章

  1. BUUOJ reverse 刮开有奖

    刮开有奖 这是一个赌博程序,快去赚钱吧!!!!!!!!!!!!!!!!!!!!!!!!!!!(在编辑框中的输入值,即为flag,提交即可) 注意:得到的 flag 请包上 flag{} 提交 拖到id ...

  2. [BUUOJ]刮开有奖reverse

    刮开有奖 这是一个赌博程序,快去赚钱吧!!!!!!!!!!!!!!!!!!!!!!!!!!!(在编辑框中的输入值,即为flag,提交即可) 注意:得到的 flag 请包上 flag{} 提交 1.查壳 ...

  3. [BUUCTF]REVERSE——刮开有奖

    刮开有奖 附件 步骤: 例行检查,无壳,32位程序 32位ida载入,shift+f12检索程序里的字符串,看到了一个base64加密的特征字符串,猜想这题用到了base64加密 从main函数开始看 ...

  4. BUUCTF 刮开有奖 WriteUp

    题目链接 https://buuoj.cn/challenges#%E5%88%AE%E5%BC%80%E6%9C%89%E5%A5%96 题解 用IDA打开,按F5反编译,双击进入DialogFun ...

  5. buu 刮开有奖

    一.查壳, 二.拖入ida,分析 直接搜字符串完全没头绪,在看了大佬的wp才找到了,关键函数. 明显那个String就是我们要求的flag,要开始分析程序. 字符串长度为8,同时这个函数对字符串进行了 ...

  6. BUUCTF--刮开有奖

    文件链接:https://buuoj.cn/files/abe6e2152471e1e1cbd9e5c0cae95d29/8f80610b-8701-4c7f-ad60-63861a558a5b.ex ...

  7. 服务端性能测试工具校验v1.1

    服务端性能测试工具校验v1.1 更新说明: 1.精简CRT运行库支持. 2.添加响应模拟测试,校验压力测试工具的响应时间统计准确性. 3.大并发请求请降低延迟时间 WEIMJSAM原创,转载请注明出处 ...

  8. 服务端性能测试工具校验v1.0

    性能测试工具对服务端进行并发测试时,如果工具本身问题或异常就会造成真实并发与实际并发有差距,要测试10000/S并发的性能结果实际到达服务端的并发达不到95%,这样的测试无效. 所以给大家共享,我做的 ...

  9. Visual.Studio.2013.IDE+visual.studio.15.preview5 编译器

    硬盘版Visual.Studio.2013.IDE + visual.studio.15.preview5 编译器 使用前注意以下事项: 1.右键-管理员权限安装,VS15补丁.exe,补丁是VS15 ...

  10. 测试工具之Charles视频教程(更新中。。。)

    应群里小伙伴学习需求,录制新版 Charles V4 系列教程,后续内容抽空更新,测试工具系列带你上王者...(ノ°ο°)ノ前方高能预警 链接:http://pan.baidu.com/s/1c16P ...

随机推荐

  1. P4921 [MtOI2018]情侣?给我烧了!

    前言 情人节写的这道题,题目名称好符合我当时的心情. 题目链接 Luogu:P4921 解法 容斥 我们发现最后要求的结果是恰好 \(k\) 对情侣坐在一起的方案数,我们就不难想到去计算恰好 \(n- ...

  2. 3月2号Android开发学习

    (2)视图基础 1.设置视图的高度 视图宽度通过属性Android:layout_width表达,视图高度通过属性android:layout_heigth表达,宽高的取值主要有以下三种 1.matc ...

  3. JS笔记(三):函数与对象

    镇楼图 Pixiv:torino 四.Function类型 Rest语法 一些函数如Math.max可以支持任意数量的参数,JS中对于这样的参数可以简单使用...来实现,使用剩余参数,它支持收集剩余的 ...

  4. 使用python的turtle库画一个冰墩墩

    目录 先看效果图 设置一个画布 画左手和手内 画轮廓和其他部分 画细节(眼睛.鼻子.嘴巴等) 画头部彩虹 画五环标志 最后(别忘记还有一个结束) 先看效果图 设置一个画布 点击查看代码 import ...

  5. OSIDP-多处理器和实时调度-10

    多处理器调度 多处理器系统分类: 1.松耦合.分布式多处理器(集群):一系列相对自治的系统组成,每个处理器有属于自己的内存和I/O通道. 2.专用处理器:有一个通用的主处理器,专用处理器由主处理器控制 ...

  6. 位置式PID和增量式PID

    PID介绍 PID 是 Proportional(比例).Integral(积分).Differential(微分)的首字母缩写:是一种结合比例.积分和微分三种环节于一体的闭环控制算法.PID 控制的 ...

  7. 实验5 开源控制器实践——POX

    实验5 开源控制器实践--POX 一.实验目的 1.能够理解 POX 控制器的工作原理: 2.通过验证POX的forwarding.hub和forwarding.l2_learning模块,初步掌握P ...

  8. []Python][simple]Serialize data with Pickle and deserialize data from pickle

    序列化 import pickle friend = {"Dan": [20, "Lodon", 123123], "Mary" : [24 ...

  9. Java反射机制知识

    modifier:修饰语 名词 JAVA 反射机制中,Field的getModifiers()方法返回int类型值表示该字段的修饰符. 其中,该修饰符是java.lang.reflect.Modifi ...

  10. 1--我们写了一个java类,那么生成一个对象占用多大的内存?

    public class Student { private long id; private long userId; private byte state; private long create ...