Уведомления

Группа в Telegram: @pythonsu

#1 Окт. 3, 2016 08:59:48

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9879
Репутация: +  853  -
Профиль   Отправить e-mail  

За что :(?

InterVi
Я с Java начинал, которую тоже ругают. Питонисты за синтаксис, сишники за потребление ресурсов.
Мне предлагали с Java начинать, я не стал, к счастью. Тогда я подумал, что это всё слишком сложно для меня - всё это программирование. Но потом мне понадобились программы (программки) и я стал изучать QBasic, потому что он был довольно простым и мощным. И вот после первых программок я понял, что мне нужно больше средств в языке, и стал изучать C++. Конечно, я круто обломился на нём, потому что не мог и шагу сделать, чтобы не увязнуть. До сих пор помню, как пытался вывести в консоль что-то через направление в cout. Купил книжку, это ничего не дало. Книжка была от Шилдта, а он, как известно, песатиль, а не программист. Поэтому три тонны мешанины из C и C++ в его исполнении убедили меня, что я не потяну C++. Вот так и было всё на уровне QBasic, пока я не прогулял геометрию и вместо неё не пошёл с другом на его занятия по Borland C++, где изучали printf() и давали задания типа нарисовать часы со стрелками и цветной флаг России на коричневой палке. И тут я понял, что я могу это делать, и стал прогуливать геометрию уже планомерно, что даже привело к диалогу типа “если нравится программирование, то переводитесь туда куда-нибудь, нельзя же прогуливать”. Когда пары закончились (их было немного, но они сделали своё дело), я поставил линукс осенью и спустя какое-то время произвольно стал заниматься по C, потому что там просто всё для этого было. Сделать программу, ничего не устанавливая, было проще простого. Потом знаний стало не хватать и я купил книжку K&R2, заказав её через Интернет по почте на Озоне. А в книжке оказалось всё совсем просто, потому что написана она и профессионалом, и программистом. Поэтому там было всего мало и только по делу. Так я её прочитал всю до системных вызовов и стал писать уже программки на C; и первой рабочей программкой стала программка для опроса модема. Модем был под столом и часто я забывал его включать, и чтобы выяснить, включен он или нет, нужно было заглядывать под стол. То есть либо ты заглядываешь под стол, либо ты открываешь браузер и у тебя нет инета. Поэтому эта программа запрашивала состояние модема и возвращала результат типа да/нет. А вот программу эту запускала кнопка на рабочем столе, которая в случае “нет” выводила сообщение, что модем выключен. Так я перестал заглядывать под стол, а просто нажимал кнопку на панели в KDE3 и смотрел.

Прошло несколько лет всяких изучений.

А вчера я писал патчер. Ну, как сказать писал, написал-то я его уже больше месяца назад. Вчера просто заполнил его новыми данными и запустил make, которая по самодельному Makefile'у собирает всё по-быстрому. (Основы make были изучены через команду info в линуксе. Она отличается от манов большей разжёванностью материала. В ней же я полностью изучил sed.) Патчер для отключения защиты в тренировочном CrackMe от FaNt0m'а. Вчера сначала написал патчер для одного CrackMe, а потом написал кейген для другого CrackMe.
Чем отличаются патчер и кейген: для патчера нужно просто найти место ненужной команды и стереть её или заменить адрес, куда программа прыгает - и всё; а для кейгена нужно проанализировать, как генерится серийник, какими вычислениями и над чем, и всё это выделить и перевести с ассемблера на C, причём перевод не прямой, так как многих прямых конструкций из ассемблера в C не существует, либо они некрасивы и считаются говнокодом.
Кейген - тоже заготовка, написал я его ещё где-то на первых CrackMe. (В программировании это называется повторное использование кода или “реюз”.) Чтобы сделать новый кейген, ты просто туда, в функцию generate() вставляешь другое содержимое и так получаешь новый алгоритм для генерации ключа. А дальше он всё спрашивает и отвечает по-старому, меняется только алгоритм генерации.
Если с патчером понятно - нужно отыскать место и вставить байты, то кейген требует перевода ассемблерного кода на C. Можно, конечно, сделать по-дурацки - типа использовать ассемблерную вставку и просто скопировать ассемблерный код в сишный исходник, но не везде тогда он будет собираться, так как в разных компиляторах используются разные диалекты ассемблера. Поэтому мы простых путей не ищем, так как знаем, что можем напороться на зависимость от системы или вообще от компилятора.

Вот это получилось
char *generate(const char *src, char *dst)
{
char *dst_start = dst;
unsigned long a, b, c, q, r, ah, al;

c = strlen(src);
c++;
while (c > 0) {
b = 0x42;
b += c;
a = *src;
src++;
a ^= b;
a <<= 5; /* must be rolled bits */
a >>= 2;
b = (b & (~0 << 8)) | 0x10;
q = a / (b & 0xff);
r = a % (b & 0xff);
a = r << 8 | q;
while (1) {
ah = (a >> 8 & 0xff);
al = a & 0xff;
a = (ah + 0x30) << 8 | al;
if (ah + 0x30 > 0x40)
a = (ah + 0x30 + 7) << 8 | al;
*dst = (a >> 8 & 0xff);
dst++;
if (al < 0x10)
a = a << 8 | 0x11;
else
break;
}
c--;
}
*dst = '\0';
return dst_start;
}
Неплохо, да? Учебный кейгенчик.

Это нужно было залезть внутрь dll-библиотеки, потому что в этом CrackMe было два усложнения: 1) экзешник и dll'шка упакованы с помощью упаковщика upx; 2) а сам серийник вычислялся не в экзешнике, а внутри dll'шки. А как в неё залезть? Вот с этим я и столкнулся. Её нужно было запустить и пройти сначала для простого ника, чтобы всё отследить. Потом это всё нужно было выделить и перевести в псевдокод. А потом уже псевдокод адаптировался под сишную запись кода. И потом уже по этому псевдокоду писался сишный код, и ещё было непонятно, правильно ли он работает. На двух длинных именах проверил - всё пашет. (Благо в своё время я изучил сишные тесты в виде cunit, а для совсем уж сложных случаев сделал питоновские юнит-тесты для любой программы на базе ввода/вывода через stdin и stdout.) Даже если бы правильно не работало, я мог бы прижать тестами функцию и исправлять её, пока не исправится.
Это была последняя из восьми CrackMe от FaNt0m'а, осталось ещё около сотни CrackMe от других ребят.
Что скажу: хоть и мало прошёл, но это уже дало возможность менять программы в винде, так как пришлось покопаться и с софтом для этого, и с переводом на нормальный язык. По крайней мере вчера я подключился к user32.dll и вызвал MessageBoxA, что дало окно из ниоткуда с текстом и кнопками.

Если ближе к питону
А вот что делать, если в Firefox'е открыто много-много вкладок, но нужно отойти от компа или припрятать их на потом и заняться другим делом в Firefox'е?
Поначалу я просто килял Firefox (через killall) и он при следующем запуске предлагал восстановить вкладки, открытые последними. Так можно было отходить от компа, но тогда в Firefox'е ничего нельзя было делать, потому что при новом запуске предлагались вкладки, которые нужно было либо снова восстановить, либо выбросить.
Чтобы решить это, можно было бы качать какой-нибудь плагин к Firefox'у, а потом ещё следить, работает ли он так, как надо. Но мы ведь знаем, что чужие плагины либо сохраняют не так, либо сохраняют не туда, либо сохраняют так, что без плагина потом в этом не разберёшься. А уж о редактировании сохранённого снаружи (типа удалить половину) и мечтать не приходится. Чаще это будет сводится к восстановлению всего, удалению ненужного и новому сохранению всего - к неповоротливой фигне.
Что делать, надо лезть в Firefox и искать, где он там понимает, что у него были открыты вкладки до кила. К счастью, в Firefox'е всё хранится в json'е и вкладки хранятся в структуре, где лежит вся информация об окнах и табах в этих окнах. Json'ить удобнее, конечно, в питоне, ибо в лине нет таких программ для обработки json'а, которые были бы везде во всех репозиториях, какая бы система ни была.

Так родился скрипт вытаскивания текущих вкладок и сохранения их в файл
[guest@localhost ~]$ cat /usr/local/bin/ffurls.py 
#!/usr/bin/env python3

# Преобразует открытые в Firefox ссылки
# в названия и ссылки в текстовом файле.

import argparse
import json

def get_js_data(fname):
with open(fname, encoding='utf-8') as fin:
return json.load(fin)

def get_ff_tu(data):
for win in data['windows']:
for tab in win['tabs']:
for entry in tab['entries']:
yield entry['title'], entry['url']

def strings_to_file(fname, seq):
with open(fname, 'w', encoding='utf-8') as fout:
for i in seq:
print(i, file=fout)

def convert_ff_to_txt(ifname, ofname):
ffurls = get_ff_tu(get_js_data(ifname))
tustrs = ('{}\n{}'.format(t, u) for t, u in ffurls)
strings_to_file(ofname, tustrs)

def get_prog_args():
desc = """
Converts Firefox session json file to
a text file with titles and urls.
"""
parser = argparse.ArgumentParser(description=desc)
parser.add_argument('ifname',
help='input Firefox session file (sessionstore.js)')
parser.add_argument('ofname', help='output urls text file')
return parser.parse_args()

def main():
args = get_prog_args()
ifname = args.ifname
ofname = args.ofname
convert_ff_to_txt(ifname, ofname)

if __name__ == '__main__':
main()
[guest@localhost ~]$
Но он слишком общий.
(Это специально сделано на случай сюрпризов от Firefox'а в новых версиях. Бывало у него такое, что менялись файлы и директории как по названиям, так и по расположению.)
Так что управлять таким файлом неудобно.

Поэтому делаем второй скрипт, уже конкретный
[guest@localhost ~]$ cat .env/scripts/ffurls.sh 
#!/bin/bash

idir="$(ls -d $HOME/.mozilla/firefox/*.default/sessionstore-backups)"
ifile="recovery.js"
odir="$HOME/Downloads"
ofile="firefox.txt"

ipath="$idir/$ifile"
opath="$odir/$ofile"

if [ -e "$opath" ]; then
n=1
while [ -e "$opath" ]; do
opath="$odir/${ofile}_$n"
((n++))
done
fi

ffurls.py "$ipath" "$opath"

exit 0
[guest@localhost ~]$
Всё, теперь он знает, где брать json у Firefox'а и в какие файлы это сохранять. На практике оказалось, что может быть несколько сохранений - типа один раз сохранил 30 вкладок, потом куда-то ушёл, пришёл и открыл другие 20 вкладок и тоже надо отойти, и как бы надо иметь и те 30, и эти 20, и чтобы никаких перемешиваний между ними. (Так появился инкремент файловых имён, которого поначалу не было.)

Так что только соместное использование языков даёт полную силу. В одном языке может не быть чего-то, что есть в другом языке. И если ты знаешь только один язык, это может привести к тому, что ты будешь писать что-то простое каким-то сложным образом. И всё только потому, что не знаешь правильного инструмента.



Отредактировано py.user.next (Окт. 3, 2016 09:20:57)

Офлайн

#2 Окт. 3, 2016 09:20:50

noob_saibot
Зарегистрирован: 2013-09-11
Сообщения: 495
Репутация: +  20  -
Профиль   Отправить e-mail  

За что :(?

py.user.next
прогуливать геометрию уже планомерно


py.user.next
while (1) {
ah = (a >> 8 & 0xff);
al = a & 0xff;
a = (ah + 0x30) << 8 | al;
if (ah + 0x30 > 0x40)
a = (ah + 0x30 + 7) << 8 | al;
*dst = (a >> 8 & 0xff);
dst++;
if (al < 0x10)
a = a << 8 | 0x11;
else
break;

А что-то типа return и рекурсии тут нельзя использовать?

py.user.next
и как бы надо иметь и те 30, и эти 20, и чтобы никаких перемешиваний между ними
Сорри за оффтоп, а вы эти вкладки потом открываете? И почему сразу нельзя прочитать то что открываешь? Просто практика показывает, если вкладки более суток висят без активации то они вам больше не понадобятся ну или по крайней мере вы их найдёте снова, а не в этой куче из 30 вкладок.

Офлайн

#3 Окт. 3, 2016 09:27:43

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9879
Репутация: +  853  -
Профиль   Отправить e-mail  

За что :(?

noob_saibot
А что-то типа return и рекурсии тут нельзя использовать?
Там нигде return нельзя использовать. break относится к внутреннему циклу. Он выходит во внешний цикл и там, во внешнем цикле, надо читать то, что находится в регистре после этого внутреннего цикла.

noob_saibot
Сорри за оффтоп, а вы эти вкладки потом открываете?
Так я их и сохраняю, чтобы потом открывать, но тогда, когда время выделил для чтения или просмотра. Я так часто сохраняю всякие видео на YouTube или когда на форуме топики открыл, а отвечать времени нет.

noob_saibot
ну или по крайней мере вы их найдёте снова, а не в этой куче из 30 вкладок.
Тут речь идёт про то, что вся эта куча из 30 вкладок должна быть прочитана, потому что она уже почищена от неинтересных. Мало того, если даже чистить времени нет, то чистить можно сам файл, который получается, потому что каждая вкладка сохраняется в виде
заголовок
https://ссылка
то есть ты всегда видишь, что это за вкладки и про что они.



Отредактировано py.user.next (Окт. 3, 2016 09:29:29)

Офлайн

#4 Окт. 3, 2016 09:37:25

ZerG
Зарегистрирован: 2012-04-05
Сообщения: 2627
Репутация: +  61  -
Профиль   Отправить e-mail  

За что :(?

гЛупо гаечным использовать гаечный ключ как палку для лыж.
Всего то нужно постичь эту мысль!
да на С можно написать что угодно - но согласитесь - написать WEB магазин на сях по трудо затратам будет в 10 раз сложнее И так далее чем сделать тоже самое на ПХП! И так далее!
Питон никогда не будет работать так же быстро как С - но есть ряд задач где оно и не нужно!
К тому же высоконагруженные участки кода можно писать на С и использовать его из питона!
Подобная тема встает постоянно на радиолюбительских форумах! Где идет извечная война между С асамблером и уже питоном! И только умные и действительно прошаренные люди пишут что каждый язык для своей задачи! Например если нужно от микроконтроллера вывод форматированных данных работа с периферией типа екрана итд то исползуют питон если обычные вычисления С а там где нужна ацкая скокрость АСМ - хотя зачастую ето мешанина!
К примеру тот же точный вольтметр - вычисление температуры лучте делать на асме - а вот вывод на екран уже на С потому что напистаь его на асме - ето рак :_)



Влодение рускай арфаграфией - это как владение кунг-фу: настаящие мастира не преминяют ево бес ниабхадимости

Офлайн

#5 Окт. 3, 2016 14:32:25

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2756
Репутация: +  184  -
Профиль   Отправить e-mail  

За что :(?

> Я с Java начинал, которую тоже ругают. Питонисты за синтаксис, сишники за потребление ресурсов. От собственного невежества ругают, как будто у них выбора нет на чём писать.

А ты действительно думаешь что жабу ругать не за что? Я так вообще питон ругаю, хотя скоро исполнится 10 лет как я знаком с этой змеюкой. А на счёт выбора ты абсолютно прав, я например на третий питон переходить не собираюсь, перейду сразу на другой ЯП когда двойка сдохнет. Благо определённые наработки имеются.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#6 Окт. 3, 2016 14:55:56

InterVi
Зарегистрирован: 2016-09-09
Сообщения: 49
Репутация: +  2  -
Профиль   Отправить e-mail  

За что :(?

Rodegast, что-то не слышал об интерпретируемых и транслируемых языках, в которых нет недостатков. Почему-то сей факт никому не мешает выполнять на них множество сложных проектов. Выбери тот язык, который тебе больше нравится и который подходит под выполнения задач.

Офлайн

#7 Окт. 3, 2016 15:05:20

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2756
Репутация: +  184  -
Профиль   Отправить e-mail  

За что :(?

> Выбери тот язык, который тебе больше нравится и который подходит под выполнения задач.

Да уже всё давно выбрано, но на него придётся переписывать уже работающие проекты, по этому до сих пор на питоне сижу.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#8 Окт. 3, 2016 16:26:46

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

За что :(?

py.user.next
Вот это получилось
А с++ там в седьмой строчке?! ;)



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#9 Окт. 3, 2016 17:15:33

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9879
Репутация: +  853  -
Профиль   Отправить e-mail  

За что :(?

PooH
А с++ там в седьмой строчке?! ;)
Короче, a, b, c в сишном коде - это ассемблерные регистры eax, ebx, ecx (32-битные). Это чтобы ты не подумал, что я просто по буквам это проименовал, как нуб, от фонаря.
Тут ещё noob_saibot говорит типа, а почему бы там рекурсию не сделать. Я просто представил рекурсию, а потом хоп и на каком-нибудь имени серийник неправильный получается - значит, ошибка где-то. Тут начинаешь сначала искать ошибку (в псевдокоде), а потом, найдя её, думаешь, а как бы теперь эту рекурсию с ошибкой переделать в рекурсию без ошибки, и тратишь на это в два раза больше времени, чем на плоский код.
Так что это ещё один аспект - код должен быть максимально простым, так как опыт показывает, что иногда нужно что-то неожиданно изменить, и чем проще в нём разобраться, тем быстрее это произойдёт. Ну, оно и в питоновском Zen'е есть.



Отредактировано py.user.next (Окт. 3, 2016 17:20:53)

Офлайн

#10 Окт. 3, 2016 18:39:27

InterVi
Зарегистрирован: 2016-09-09
Сообщения: 49
Репутация: +  2  -
Профиль   Отправить e-mail  

За что :(?

Rodegast
на него придётся переписывать уже работающие проекты
зачем?

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version