小游戏: crack licensechecker0x03 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hxndg
V2EX    信息安全

小游戏: crack licensechecker0x03

  •  
  •   hxndg 2022-09-03 20:42:56 +08:00 1396 次点击
    这是一个创建于 1136 天前的主题,其中的信息可能已经有所发展或是发生改变。

    每天有时候日常工作做的很烦,疲乏之余做个小 crackme 玩下,这个的难度比较简单,进入 main ,跟着流程走一遍基本就明白了.crackme 的下载路径在这里: https://crackmes.one/crackme/62072dd633c5d46c8bcbfd9b

    可以自己看下面的代码和注释来理解,不清楚的话看最底下的流程讲解

     Dump of assembler code for function main: 0x0000555555555179 <+0>: push %rbp #标准开局,保存堆栈环境 0x000055555555517a <+1>: mov %rsp,%rbp 0x000055555555517d <+4>: sub $0x30,%rsp #非常标准的对应 main 函数的两个参数 int main(int argc, char** argv),这个是 argc 0x0000555555555181 <+8>: mov %edi,-0x24(%rbp) 0x0000555555555184 <+11>: mov %rsi,-0x30(%rbp) #对应 argv 0x0000555555555188 <+15>: mov %fs:0x28,%rax 0x0000555555555191 <+24>: mov %rax,-0x8(%rbp) 0x0000555555555195 <+28>: xor %eax,%eax # #比较有没有参数,换言之有没有输入参数,如果有输入参数跳转到下面箭头指的地方 0x0000555555555197 <+30>: cmpl $0x2,-0x24(%rbp) ------- 0x000055555555519b <+34>: je 0x5555555551c5 <main+76> | # 没输入参数的话直接开始调用 printf 函数打印下面的格式 | 0x000055555555519d <+36>: mov -0x30(%rbp),%rax | 0x00005555555551a1 <+40>: mov (%rax),%rax | 0x00005555555551a4 <+43>: mov %rax,%rsi | # 格式的字符对应"Usage : %s <license pass code here [numbers only]>\n" | 0x00005555555551a7 <+46>: lea 0xe5a(%rip),%rax # 0x555555556008 | 0x00005555555551ae <+53>: mov %rax,%rdi | 0x00005555555551b1 <+56>: mov $0x0,%eax | 0x00005555555551b6 <+61>: callq 0x555555555050 <printf@plt> | 0x00005555555551bb <+66>: mov $0x0,%edi | 0x00005555555551c0 <+71>: callq 0x555555555070 <exit@plt> | #下面的两个地址存储着两个参数 | # 清空两个数值,这里存储着一个计算出来的和 ------> 0x00005555555551c5 <+76>: movl $0x0,-0x10(%rbp) #这个地址存储的是处理过的字符串的字符的个数 0x00005555555551cc <+83>: movl $0x0,-0xc(%rbp) -- 0x00005555555551d3 <+90>: jmp 0x555555555201 <main+136> --------> 0x00005555555551d5 <+92>: mov -0x30(%rbp),%rax #还是拿到输入的数字的位置 | | 0x00005555555551d9 <+96>: add $0x8,%rax | | 0x00005555555551dd <+100>: mov (%rax),%rdx | | 0x00005555555551e0 <+103>: mov -0xc(%rbp),%eax # 这个存储着处理过的字符串字符的个数,第一次是 0 | | 0x00005555555551e3 <+106>: cltq | | 0x00005555555551e5 <+108>: add %rdx,%rax #找到当前处理的字符 | | #取 rax ,实际上就是输入的数字所在的字符串的 1byte ,拓展到 eax 里 | | 0x00005555555551e8 <+111>: movzbl (%rax),%eax | | 0x00005555555551eb <+114>: mov %al,-0x11(%rbp) #丢到栈里面,可以看到是刚才-0x10(%rbp)的低一位 | | 0x00005555555551ee <+117>: lea -0x11(%rbp),%rax | | 0x00005555555551f2 <+121>: mov %rax,%rdi | | #转换为整数,整个过程是一个循环,就是在不断地将每一位转换为数字,然后加到-0x10(%rbp)上 | | 0x00005555555551f5 <+124>: callq 0x555555555060 <atoi@plt> | | #eax 存储着从字符转换为数字的结果(返回值),存储到求和到刚才舒适的存储和的位置 | | 0x00005555555551fa <+129>: add %eax,-0x10(%rbp) | | #addl 加了一个 1 ,实际上就是诸位比较,还是继续运行, | | 0x00005555555551fd <+132>: addl $0x1,-0xc(%rbp) | | #argv 的起始地址, | --->0x0000555555555201 <+136>: mov -0x30(%rbp),%rax | # 偏移 8 字节,实际上目的是找到第二个元素,也就是我们输入参数所对应字符串的地址 | 0x0000555555555205 <+140>: add $0x8,%rax | # 将元素的值赋值给 rax ,就是输入的数字的所在字符串的地址, | 0x0000555555555209 <+144>: mov (%rax),%rax | 0x000055555555520c <+147>: mov %rax,%rdi | # 对字符串调用 strlen 判断长度 | 0x000055555555520f <+150>: callq 0x555555555040 <strlen@plt> | # 返回的字符串长度放在了 eax 里面,和已经操作的字符串的字符个数比较一下,看看是不是处理完了 | 0x0000555555555214 <+155>: cmp %eax,-0xc(%rbp) --- 0x0000555555555217 <+158>: jl 0x5555555551d5 <main+92> #比较输入的参数字符串每一个转换为数字后加起来以后是不是 0x32 ,所以构造一个字符串各位求和是 0x32 的即可 0x0000555555555219 <+160>: cmpl $0x32,-0x10(%rbp) 0x000055555555521d <+164>: jne 0x555555555238 <main+191> 0x000055555555521f <+166>: lea 0xe1a(%rip),%rax # 0x555555556040 0x0000555555555226 <+173>: mov %rax,%rdi 0x0000555555555229 <+176>: callq 0x555555555030 <puts@plt> 0x000055555555522e <+181>: mov $0x0,%edi 0x0000555555555233 <+186>: callq 0x555555555070 <exit@plt> 0x0000555555555238 <+191>: lea 0xe25(%rip),%rax # 0x555555556064 0x000055555555523f <+198>: mov %rax,%rdi 0x0000555555555242 <+201>: callq 0x555555555030 <puts@plt> 0x0000555555555247 <+206>: mov $0x0,%edi 0x000055555555524c <+211>: callq 0x555555555070 <exit@plt> 

















































































































    • 首先检查有没有参数,argc 是不是等于 2 ,不等于 2 报错退出
    • 初始化两个变量,一个存储处理过的位数,一个存储求和的结果
    • 判断当前 处理过的字符串的字符个数和整个字符串的长度,如果没处理完开始循环
    • 找到参数对应字符串的一个 char ,然后转换为整数加到求和的结果里,循环上一步直到处理完成
    • 比较求和的结果和 0x32 是不是相等,相等即成功

    所以构造一个求和是 0x32 的数字字符串即可,999995 ,通过

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1464 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 16:44 PVG 00:44 LAX 09:44 JFK 12:44
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86