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

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

轉:Cracking Sublime Text 3

2019-11-14 11:57:50
字體:
來源:轉載
供稿:網友

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!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产欧美一区二区三区久久| 亚洲精品视频网上网址在线观看| 亚洲成avwww人| 久久这里有精品视频| 在线精品高清中文字幕| 亚洲无线码在线一区观看| 91超碰中文字幕久久精品| 成人av在线亚洲| 国产精品免费观看在线| 欧美性高跟鞋xxxxhd| 欧美性猛交xxxx偷拍洗澡| 国产成人精品999| 粉嫩av一区二区三区免费野| 俺去啦;欧美日韩| 亚洲欧美在线第一页| 国产精品电影一区| 久久久成人的性感天堂| 成人a在线观看| 国产精品扒开腿做爽爽爽的视频| 91在线视频精品| 91精品国产综合久久香蕉922| 欧美精品aaa| 精品香蕉一区二区三区| 韩日精品中文字幕| 亚洲视频综合网| 亚洲国产天堂久久国产91| 国产精品美女午夜av| 欧美高清激情视频| 日韩国产高清污视频在线观看| 欧美大人香蕉在线| 国产精品爽黄69天堂a| 免费99精品国产自在在线| 欧美性感美女h网站在线观看免费| 国产乱人伦真实精品视频| 国产亚洲人成网站在线观看| 日韩激情av在线播放| 欧美大片va欧美在线播放| 久热精品视频在线| 日韩欧美a级成人黄色| 欧美激情成人在线视频| 搡老女人一区二区三区视频tv| 欧美xxxx14xxxxx性爽| 成人午夜激情免费视频| 欧美日韩国产精品专区| 国产欧美 在线欧美| 亚洲激情在线观看视频免费| 久久久99免费视频| 欧美激情第99页| 欧美日韩在线一区| 在线看欧美日韩| 亚洲大胆人体视频| 国产精品久久久久久久天堂| 97婷婷大伊香蕉精品视频| 国产精品网址在线| 亚洲一区二区在线| 欧美午夜www高清视频| 久久99视频免费| 日本精品一区二区三区在线| 高清欧美电影在线| 日韩综合中文字幕| 韩日精品中文字幕| 色婷婷成人综合| 91亚洲国产精品| 中文字幕免费精品一区| 国产精品揄拍一区二区| 日韩视频中文字幕| 久久久久久香蕉网| 欧美小视频在线观看| 欧美国产日韩精品| 日韩中文字幕免费看| 国产国语刺激对白av不卡| 亚洲一区二区在线| 日韩在线免费高清视频| 亚洲国产欧美精品| 欧美黑人极品猛少妇色xxxxx| 91精品国产91久久久久久久久| 欧美一级视频一区二区| 92国产精品久久久久首页| www国产精品视频| 国产日韩精品在线观看| 欧美日韩一区二区三区在线免费观看| 国产精品青草久久久久福利99| 欧美激情在线有限公司| 91超碰caoporn97人人| 日韩视频一区在线| 国产91免费观看| 91在线直播亚洲| 国产在线观看91精品一区| 国产成人精品在线播放| 亚洲黄页网在线观看| 国产精品欧美一区二区三区奶水| 精品欧美国产一区二区三区| 最近2019免费中文字幕视频三| 国内精品久久久久影院优| 午夜精品蜜臀一区二区三区免费| 韩国三级日本三级少妇99| 一区二区欧美日韩视频| 日韩欧美中文免费| 日韩欧美高清视频| 国产日本欧美视频| 91精品国产91久久久久| 国产精品wwww| 久久久av亚洲男天堂| 91亚洲精华国产精华| 国产精品亚洲精品| 久久高清视频免费| 在线播放国产一区中文字幕剧情欧美| 久久成人综合视频| 97在线观看免费高清| 国自产精品手机在线观看视频| 成人天堂噜噜噜| 亚洲精品suv精品一区二区| 日韩视频免费看| 91热精品视频| 欧美黑人极品猛少妇色xxxxx| 日韩欧美综合在线视频| 久久久久久久久久久国产| 热久久视久久精品18亚洲精品| 91牛牛免费视频| 亚洲自拍偷拍网址| 国产亚洲精品久久久优势| 精品久久久在线观看| 亚洲国产成人久久综合一区| 米奇精品一区二区三区在线观看| 久久人人97超碰精品888| 欧美国产第一页| 亚洲自拍av在线| 日韩视频免费观看| 中文字幕v亚洲ⅴv天堂| 久久99久久99精品中文字幕| 国色天香2019中文字幕在线观看| 日韩在线精品视频| 国产成人在线精品| 国产偷国产偷亚洲清高网站| 激情亚洲一区二区三区四区| 97在线精品视频| 国产亚洲精品一区二555| 日韩精品在线电影| 国产一区二区三区在线视频| 久久久久国产视频| 久久久久久久亚洲精品| 亚洲精品自拍视频| 亚洲精品国产精品自产a区红杏吧| 91精品国产高清久久久久久| 精品国产户外野外| 日韩成人在线视频网站| 国产91九色视频| 亚洲国产欧美一区二区三区同亚洲| 成人做爰www免费看视频网站| 亚洲国产欧美一区| 欧美日韩成人黄色| 久热精品视频在线观看一区| 亚洲九九九在线观看| 国产精品入口免费视频一| 精品久久久一区二区| 欧美日韩激情美女| 69久久夜色精品国产7777| 国产精品一区电影| 91精品视频播放| 久久久国产视频91| 亚洲天堂av在线播放| 亚洲一区二区在线| 色偷偷亚洲男人天堂| 日韩视频免费大全中文字幕|