亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

轉:Cracking Sublime Text 3

2019-11-14 12:00:36
字體:
來源:轉載
供稿:網友

Auther: Fernando Domínguez Delgado

OS X native software is written in Objective-C, a superset of C which is not very hard to hack away. In this post I will try to demonstrate the basics of reverse engineering in said platform.

The goal

Our goal will be to stop the annoying Sublime Text pop-up from reminding you to buy a license each now and then (but you totally should if you are going to use it). I will be using Sublime Textlatest build in the time of writting, 3114, for OS X 64-bit.

For the disassembling + patching I will be using Hopper, a disassembler for Mach0 and ELFexecutables which also PRovides handy C-like pseudo-code.

Requisites

Basic software development experienceBasic assembly knowledgeBasic C knowledge

Getting started

First time you open a disassembled binary it looks scary. There is a ton of code and it is not very readable, so we need some references to get started. Strings are a good starting point as they are coded as clear text ASCII in the binary itself.

In this case it is a particularly good idea as what we are trying to do is stop a string from showing. So, to begin with, we'll be searching for the string contained on the pop-up with Hopper's built in string search.

 

 The string is found on 0x0000000100480a36 and it is only referenced by 0x0000000100072ad0. If you hop to that address you will find yourself in an asm procedure. This procedure can only be the one that shows the pop-up, as it is the only reference to the string shown in the pop-up. Nevertheless, to gain a better understanding of what this procedure does let's use the asm to pseudo-code functionality built on Hopper.

int maybe_show_nag_screen()() {      if (*(int8_t *)_g_valid_license == 0x0) {            rax = time_now_milliseconds();            rbx = rax;            rax = rax - *maybe_show_nag_screen()::last_show_time;            if (rax >= 0xa4cb80) {                    *(int32_t *)maybe_show_nag_screen()::count_since_last_nag = *(int32_t *)maybe_show_nag_screen()::count_since_last_nag + 0x1;                    rax = rand();                    rax = (rax & 0xf) == 0x0 ? 0x1 : 0x0;                    rdx = *(int32_t *)maybe_show_nag_screen()::count_since_last_nag;                    rcx = rdx <= 0x2 ? 0x1 : 0x0;                    if (rdx <= 0x8) {                            rax = rax & rcx;                            COND = rax == 0x0;                            if (!COND) {                                    *(int32_t *)maybe_show_nag_screen()::count_since_last_nag = 0x0;                                    *maybe_show_nag_screen()::last_show_time = rbx;                                    rax = px_show_message_ok_cancel(0x0, "Hello! Thanks for trying out Sublime Text./n/nThis is an unregistered evaluation version, and although the trial is untimed, a license must be purchased for continued use./n/nWould you like to purchase a license now?", "This is an unregistered copy", "Purchase");                                    if (rax != 0x0) {                                            rax = px_open_url("https://www.sublimetext.com/buy");                                    }                            }                    }                    else {                            *(int32_t *)maybe_show_nag_screen()::count_since_last_nag = 0x0;                            *maybe_show_nag_screen()::last_show_time = rbx;                            rax = px_show_message_ok_cancel(0x0, "Hello! Thanks for trying out Sublime Text./n/nThis is an unregistered evaluation version, and although the trial is untimed, a license must be purchased for continued use./n/nWould you like to purchase a license now?", "This is an unregistered copy", "Purchase");                            if (rax != 0x0) {                                    rax = px_open_url("https://www.sublimetext.com/buy");                            }                    }            }    }    return rax;}The code is pretty self explanatory. If _g_valid_license is 0x0, i.e: FALSE and the pop-up has not been shown for a while, show it. Now, to the asm.

If we take into account that a C if is encoded as a cmp and some sort of jump statement we can clearly see that the if statement is contained in the following statements:

cmp byte [ds:_g_valid_license], 0x0  jne 0x100072b0  

as cmp byte [ds:_g_valid_license], 0x0 compares _g_valid_license to 0x0 and jne 0x100072b0jumps to the specified address if the comparison 'returned' not equal, i.e: the license is valid, efectively skipping the part of the procedure that shows the pop-up.

So in order not to launch the pop-up ever again we can simply change the jne statement for an unconditional jump statement, jmp, to the same address.

We can do that from Hopper itself pressing ?A on the jne line. Once you modify this line Hooper will lose track of what kind of data this is, thus the sections will be highlighted in white instead of the light yellow we had before. To solve this you can click on the first line and tag it as "P(rocedure)" on the top bar icon. Once you tag the procedure again Hooper will show the part we skipped in white to signal that it is no longer reachable. Furthermore, if you switch to pseudo-code again it will show this:

int maybe_show_nag_screen()() {      CMP(*(int8_t *)_g_valid_license, 0x0);    return rax;}

Aand that's pretty much it, the license pop-up will not bother you again. But that does not feel like we achieved much, does it? Although we achieved our goal we didn't register the product, we didn't fiddle with the licensing methods nor we generated a keygen.

Moving further

Licensing

We are following the same approach for this part. We know that if we introduce an invalid license the following shows up.

And that looks like a string we could use as an initial reference. If we jump to the procedure that references the string we come up with the following:

int license_window::on_ok_clicked()() {      r15 = rdi;    TextBuffer::str();    toUtf8(var_30);    if ((var_48 & 0x1) != 0x0) {            Operator delete(var_38);    }    *(int8_t *)_g_valid_license = 0x0;    if ((*(int8_t *)_g_license_name & 0x1) == 0x0) {            *(int8_t *)0x100677959 = 0x0;            *(int8_t *)_g_license_name = 0x0;    }    else {            *(int8_t *)*0x100677968 = 0x0;            *0x100677960 = 0x0;    }    *(int32_t *)_g_license_seats = 0x0;    rax = var_30 & 0xff;    if ((rax & 0x1) == 0x0) {            rax = rax >> 0x1;    }    else {            rax = var_28;    }    if (rax != 0x0) {            rax = check_license(var_30, _g_license_name, _g_license_seats, var_4C);            *(int8_t *)_g_valid_license = COND_BYTE_SET(E);            if (rax == 0x1) {                    encode_decode_license(var_30);                    get_license_path();                    if ((var_68 & 0x1) == 0x0) {                            rdi = var_67;                    }                    else {                            rdi = var_58;                    }                    rdx = var_30 & 0xff;                    if ((rdx & 0x1) == 0x0) {                            rsi = var_2F;                            rdx = rdx >> 0x1;                    }                    else {                            rdx = var_28;                            rsi = var_20;                    }                    rbx = write_file(rdi, rsi, rdx, 0x1);                    std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(var_68);                    if (rbx == 0x0) {                            r14 = control::get_px_window();                            get_license_path();                            rax = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::insert(var_98, 0x0, "Unable to write license file: ");                            var_70 = *(rax + 0x10);                            rcx = *rax;                            var_80 = rcx;                            *(rax + 0x10) = 0x0;                            *(rax + 0x8) = 0x0;                            *rax = 0x0;                            if ((var_80 & 0x1) == 0x0) {                                    rsi = var_7F;                            }                            else {                                    rsi = var_70;                            }                            px_show_message(r14, rsi);                            std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(var_80);                            std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(var_98);                    }                    create_thread(notify_license_entered_thread(void*), sign_extend_64(var_4C));                    rax = var_4C;                    if ((rax > 0xcf20b) && (rax > 0xab247)) {                            rax = control::get_px_window();                            px_show_message(rax, "Thanks for purchasing!");                    }                    else {                            rax = control::get_px_window();                            px_show_message(rax, "Thanks for trying out Sublime Text 3!/n/nSublime Text 3 is a paid upgrade from Sublime Text 2, and an upgrade will be required for use when 3.0 is released./n/nUntil then, please enjoy Sublime Text 3 Beta.");                    }            }            else {                    if (rax != 0x4) {                            if (rax == 0x3) {                                    rax = control::get_px_window();                                    px_show_error(rax, "That license key is no longer valid.");                            }                            else {                                    if (rax == 0x2) {                                            rax = control::get_px_window();                                            px_show_error(rax, "That license key doesn't appear to be valid./n/nPlease check that you have entered all lines from the license key, including the BEGIN LICENSE and END LICENSE lines.");                                    }                            }                    }                    else {                            rax = control::get_px_window();                            px_show_error(rax, "That license key has been invalidated, due to being shared./n/nPlease email sales@sublimetext.com to get your license key reissued.");                    }            }    }    else {            get_license_path();            if ((var_B0 & 0x1) == 0x0) {                    rdi = var_AF;            }            else {                    rdi = var_A0;            }            delete_file(rdi);            std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(var_B0);    }    if (*(r15 + 0x150) != 0x0) {            std::__1::function<void (r15 + 0x130);    }    rdi = *(r15 + 0x28);    rax = *rdi;    rax = *(rax + 0x88);    (rax)(rdi);    rax = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(var_30);    return rax;}Now, if we have a closer look at the top lines we can see that the license checking is taking place in these lines:

rax = check_license(var_30, _g_license_name, _g_license_seats, var_4C);              *(int8_t *)_g_valid_license = COND_BYTE_SET(E);

And depending on the value of rax one action or another will take place. Judging by the strings contained on the if blocks these are the possible outcomes of check_license by return value:

0x1: License is valid, as the message Thanks for purchasing will show.0x2: License is invalid, as the message That license key doesn't appear to be valid./n/nPlease check that you have entered all lines from the license key, including the BEGIN LICENSE and END LICENSE lines.is printed.0x3: The license is no longer valid.0x4: The license has been invalidated due to piracy.

So, if we change the if comparison from 0x1 to 0x2 we will have our random string registered.

Going back to the asm code is pretty obvious that this comparison is taking place in these lines:

As the check_license subroutine is being called and the outcome (rax) is being compared to 1. Now, let's change that 1 to a 2.

And.

Tada!


上一篇:C++11新特性

下一篇:Leetcode 112. Path Sum

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品美女主播在线观看纯欲| 亚洲欧美日韩精品| 国产香蕉精品视频一区二区三区| 欧美性20hd另类| 欧美成人精品三级在线观看| 成人福利在线观看| 成人h视频在线观看播放| 亚洲天堂av图片| 宅男66日本亚洲欧美视频| 日韩av影片在线观看| 中文字幕精品影院| 亚洲欧美日韩国产成人| 91精品视频免费| 亚洲成人激情小说| 福利微拍一区二区| 亚洲欧洲黄色网| 欧美午夜激情在线| 欧美在线免费观看| 亚洲韩国日本中文字幕| 深夜福利一区二区| 日韩av在线网址| 国产精品久久久久久久电影| 国产91精品高潮白浆喷水| 国内精品久久久久影院优| 久久99久久久久久久噜噜| 国产成人久久久精品一区| 日韩最新免费不卡| 国产剧情久久久久久| 国产这里只有精品| 亚洲在线免费视频| 国产视频精品在线| 国产一区视频在线| 国产精品美女www| 欧美性生交xxxxxdddd| 亚洲免费成人av电影| 色视频www在线播放国产成人| 在线成人一区二区| 国产一区二区三区在线看| 日韩在线视频播放| 4438全国成人免费| 国产成人a亚洲精品| 日韩免费av一区二区| 久久6精品影院| 久久久精品一区二区| 91成人在线观看国产| 日韩亚洲欧美中文高清在线| 久久精品91久久久久久再现| 亚洲毛片一区二区| 日本精品免费一区二区三区| 成人在线精品视频| 欧美成人亚洲成人日韩成人| 国产精品日韩在线观看| 亚洲欧洲第一视频| 日韩电影中文字幕| 久久精品国产99国产精品澳门| 亚洲性日韩精品一区二区| 国产欧美在线播放| 欧美成人高清视频| 精品久久久久久久久久久| 欧美性少妇18aaaa视频| 日韩最新在线视频| 粉嫩av一区二区三区免费野| 97avcom| 91免费精品视频| 国产美女精品视频| 亚洲xxxx18| 91色琪琪电影亚洲精品久久| 日韩av综合网| 欧美日韩激情小视频| 性欧美长视频免费观看不卡| 国产精品99久久久久久久久| 国产精品电影观看| 欧美精品一区在线播放| 欧美日韩国产一区在线| 欧美在线视频一区二区| 久久久久北条麻妃免费看| 久久99久久99精品免观看粉嫩| 国产一区二区免费| 亚洲香蕉伊综合在人在线视看| 亚洲www永久成人夜色| 中文字幕亚洲欧美日韩在线不卡| 欧美午夜激情小视频| 精品日本高清在线播放| 国产福利精品视频| 最近2019中文字幕大全第二页| 国产精品欧美久久久| 国产精品爽爽爽爽爽爽在线观看| 日韩视频免费大全中文字幕| 国产精品久久国产精品99gif| 国产mv免费观看入口亚洲| 欧美日韩国产第一页| 2020久久国产精品| 日韩av免费看| 成人乱色短篇合集| 成人免费视频在线观看超级碰| 国产日韩换脸av一区在线观看| 中文日韩电影网站| 精品女同一区二区三区在线播放| 欧美成人自拍视频| 久久久久久成人精品| 97人人爽人人喊人人模波多| 日韩高清人体午夜| 日av在线播放中文不卡| 色偷偷av亚洲男人的天堂| 亚洲国产精品va在线观看黑人| 久久久久久国产精品三级玉女聊斋| 精品国产一区二区三区久久久狼| 日韩亚洲欧美中文在线| 亚洲国产精品美女| 欧美国产第二页| 九色精品美女在线| 日韩欧美在线视频观看| 国产成人综合亚洲| 国产精品嫩草视频| 国产精选久久久久久| 亚洲石原莉奈一区二区在线观看| 在线亚洲午夜片av大片| 欧美专区在线观看| 中文字幕精品久久| 成人黄色片在线| 久久久影视精品| 日韩有码在线播放| xx视频.9999.com| 国产精品视频中文字幕91| 精品网站999www| 91色在线观看| 91亚洲永久免费精品| 欧美香蕉大胸在线视频观看| 欧美美最猛性xxxxxx| 国产精品久久久久久久7电影| 最近更新的2019中文字幕| 91中文字幕一区| 国产日韩精品综合网站| 日韩中文字幕精品视频| 亚洲精品美女视频| 日韩欧美亚洲国产一区| 欧美精品一二区| 欧美日韩午夜激情| 国产精品盗摄久久久| 欧美中文在线观看| 欧美日韩第一视频| 国内精品久久久久久影视8| 成人美女av在线直播| 欧美日韩亚洲一区二区三区| 日韩国产高清污视频在线观看| 不卡在线观看电视剧完整版| 亚洲国产中文字幕在线观看| 永久免费毛片在线播放不卡| 国产精品亚洲美女av网站| 91精品久久久久久久久久久| 国产精品久久久久久久久男| 国产www精品| 日本成人免费在线| 亚洲免费av电影| 亚洲美女动态图120秒| 日韩欧美在线视频观看| 国语自产偷拍精品视频偷| 国产国语刺激对白av不卡| 久久99精品国产99久久6尤物| 欧美午夜美女看片| 久久91超碰青草是什么| 91久久精品美女高潮| 成人网在线视频| 亚洲成人激情图|