Файл cards.dbf со списком карт можно экспортировать из программы PCards.exe. Скрипт можно использовать для поиска "кредитных карт" и быть в курсе общих долгов, либо как в прошлой статье для быстрого выявления анамальных карт с отрицательным балансом.
#!/usr/bin/env python
from dbfpy import dbf
mincards = open('mincards.txt', 'w')
cards = dbf.Dbf("cards.dbf")
cardscount = 0
amoney = 0
for rec in cards:
if rec["RESTSUM"] < 0:
mincards.writelines('card number: '+str(rec["CARD"])+' cash: '+str(rec["RESTSUM"])+'\n')
cardscount += 1
amoney += rec['RESTSUM']
mincards.write(str(cardscount)+' cards in the amount of '+str(amoney));
mincards.close()
cards.close()
Не акцентируя внимание на производителе и на названии программного обеспечения, поведаю об одной уязвимости персональной дисконтной системы и автоматизации ресторанного бизнеса. На изобаражении снизу приведена структура сети только из участников основного действа:
Под PDS подразумевается станции с клиенской частью, которую юзает кассир, пополняя и изымыя средства с пластиковых клиентских карт с магнитной лентой. Заранее хочу предупредить, что в статье Я описываю свое видение работы и взаимодействия узлов данной клиент серверной архитектуры. Сервер работает как БД со списком карт, балансом и хранит все транзации, а так же обрабатывает запросы от PDS. У программы PDS есть такая функция как авторизация карты в ручную по номеру, в обход картридера. В итоге мы имеем:
1) кассир + его сообщник с мобилой.
2) уязвимость вышеприведенной схемы(чуть ниже раскрою суть)
Кассир(PDS_2) фиктивно пополняет карту(в денежный ящик средства не вносятся), отдает ее сообщнику и тут же ему звонит, тот в свою очередь спускается на первый этаж заведения к PDS_1. Кассир(PDS_2) в это время набивает номер карты в ручную и видит на экране положительный баланс(например 5000р.), ему остается ждать команды по тел. Сообщник совершенно легально снимает деньги у кассира(PDS_1, тот не слухом не духом), и дает команду на старт по телефону. Соответственно в чеке новый баланс = 0, PDS_2 остается только нажать кнопку изъятие средств, увидеть новый баланс = -5000р. и остаться не при делах(сумма денежного ящика приравнивается к сумме в X отчете). Profit..
Мое видение как обрабатывает такие операции система:
При авторизации карты на PDS, запросом на сервер изымается информация о карте и ее балансе. Когда деньги изымаются PDS_1 отправляет запрос, на сервере баланс карты становится нулевым. В это время на PDS_2 еще открыто окно с авторизованной картой и балансом 5000р. подставной кассир изымает деньги, прога сверяет данные полученные за долго до этого с введеной суммой, и если она не больше, тоже отправляет запрос на сервер, тот его обрабатывает, карта уходит в -5000р. При этом у карты не выставлено никакого кредита и прочих параметров. Вот собственно и все.
Если же подставной кассир снимет денежку первее сообщника, то на кассе с нормальным кассиром будет палево в чеке и на экране компьютера "Новый баланс -5000р." Так же карты с отрицательным балансом видны на самом сервере в проге. А по транзакциям и индивидуальному коду кассира можно его вычислить.
Неплохо было бы посидеть со снифером у хаба и посмотреть как передаются запросы с кассы к серверу. А так же в скором времени будет написан скрипт для автоматизации поиска карт с отрицательным балансом в БД.
Качаем нужный образ, открываем консоль выполняем следующие команды, заменяя пути и имена устройств на свои. sdX в моем случае это sdb, имя устройства можно узнать командой dmesg. Образ у меня лежал в домашней дериктории: /home/vince/debian-6.0.4-i386-DVD-1.iso
- сделает ноутбук точкой доступа wifi в пару кликов. Бесплатная версия выполняет самый нужный мимимум, раздает инет и показывает количество активных пользователей, а так же их маки и ip. Тут же во вкладке Clients, можно отключить от сети отдельно выбранные устройства. После установки делаем следующее: даем имя нашей "точке доступа"(Hotspot Name), обязательно запароливаем её(Password), в поле Internet to Share указываем интерфейс который фактически имеет подключение к интернет. В Share Over выбираем wi-fi интерфейс выступающий в последующем точкой доступа, Sharing Mode отвечает за тип шифрования, WPA2 WEP либо открытая для всех точка доступа(Ad-Hoc Open). Где то в сети видел что версия ОС Windows 7 должна быть выше домашней базовой. Тестил на Windows 7 Домашняя базовая x64, все работает сразу после установки..
Недавно сталкнулся с проблемой добавления youtube видео в материалы движка joomla, по той простой причине, что редактор вырезает теги iframe.. Есть много вариантов обойти этот ньюанс, самый юзабельный, простой в установке так и в использовании - плагин . Поддерживаемые версии 1.5 - 2.5 включительно на данный момент. Скачиваем архив, либо сразу указываем в админке joomla откуда его скачать и установить, на вкладке управления плагинами, просто включаем его, в панели справа указываем параметры отображаемого видео, сохраняем настройки, и пользуемся в удовольствие. Материалы с youtube добавляются вот таким обазом: {youtube}ZRXO8XBwRhc{/youtube} все что расположено между двумя псевдотегами youtube это код нужного вам видео. Так же у плагина есть возможность отображать видео из выбранной вами папки на сервере вашего хостинга {flv}file_name{/flv} , все настраивается за 5 секунд в настройках плагина.
Такой реализации в интернете я еще не видел, не в плане кода, а алгоритма, число помещается в список, соответственно у каждой цифры в числе появляется индекс, именно по нему программа распознает к какому порядку пренадлежит число и как его обрабатывать.. Честно говоря говнокод начал появлятся и расти после того как решил взять диапазон выше 999. До этого момента код выглядел не так ужасно и более компактно. Так как pyton только начал изучать, вдоволь поработал с дебаггером, и сразу же на практике попробовал многие вещи..
P.S. Слил код на , ребята посчитали что до тематики сайта этому произведению еще далеко..
#!/usr/bin/env python
def add_end(position, num):
end_str = ''
if (position == 5) and (num in [0,5,6,7,8,9]):
end_str = th[0]
return end_str
elif (position == 5) and (num in [2,3,4]):
end_str = th[2]
return end_str
elif (position == 5) and (num == 1):
end_str = th[1]
return end_str
if (position == 2) and (num in [0,5,6,7,8,9]):
end_str = th[4]
return end_str
elif (position == 2) and (num in [2,3,4]):
end_str = th[7]
return end_str
elif (position == 2) and (num == 1):
end_str = th[3]
return end_str
return ('')
dec1 = ['', ' один', ' два', ' три', ' четыре', ' пять', ' шесть', ' семь', ' восемь', ' девять', ' десять', ' одиннадцать', ' двенадцать', ' тринадцать', ' четырнадцать', ' пятнадцать', ' шестнадцать', ' семнадцать', ' восемнадцать', ' девятнадцать']
dec2 = ['', '', ' двадцать', ' тридцать', ' сорок', ' пятьдесят', ' шестьдесят', ' семьдесят', ' восемьдесят', ' девяносто']
dec3 = ['', ' сто', ' двести', ' триста', ' четыреста', ' пятьсот', ' шестьсот', ' семьсот', ' восемьсот', ' девятьсот']
th = [' тысяч', ' тысяча', ' тысячи', ' миллион', ' миллионов', 'одна', 'две', ' миллиона']
numb = input('введите число: ')
mysum = []
max_len = 9;
zero = max_len - len(numb)
for i in range(zero):
mysum.append('0')
for char in numb:
mysum.append(char)
for i in range(max_len):
mysum[i] = int(mysum[i])
for element in mysum:
if int(element) != 0:
start_rank = mysum.index(element)
break
grouprank1 = [2,5,8]
grouprank2 = [1,4,7]
grouprank3 = [0,3,6]
mystr = ''
while start_rank < max_len:
if start_rank in grouprank1:
if (start_rank == 5) and (mysum[start_rank] == 1):
mystr += th[5] + str(add_end(start_rank, mysum[start_rank]))
elif (start_rank == 5) and (mysum[start_rank] == 2):
mystr += th[6] + str(add_end(start_rank, mysum[start_rank]))
elif start_rank == 5:
mystr += dec1[mysum[start_rank]] + str(add_end(start_rank, mysum[start_rank]))
if (start_rank == 2) and (mysum[start_rank] == 1):
mystr += dec1[mysum[start_rank]] + str(add_end(start_rank, mysum[start_rank]))
elif (start_rank == 2) and (mysum[start_rank] == 2):
mystr += dec1[mysum[start_rank]] + str(add_end(start_rank, mysum[start_rank]))
elif start_rank == 2:
mystr += dec1[mysum[start_rank]] + str(add_end(start_rank, mysum[start_rank]))
if start_rank == 8:
mystr += dec1[mysum[start_rank]]
start_rank += 1
if (start_rank in grouprank2) and (mysum[start_rank] == 1):
index_dec2 = str(mysum[start_rank]) + str(mysum[start_rank+1])
mystr += dec1[int(index_dec2)]
start_rank += 2
if start_rank in grouprank2:
mystr += dec2[mysum[start_rank]]
start_rank += 1
if start_rank in grouprank3:
mystr += dec3[mysum[start_rank]]
start_rank += 1
print(mystr)
Я назвал списки стеками из за имеющихся у них двух функций pop() и append(), первая изымает элемент с конца списка, а вторая наоборот добавляет. Для реализации очереди нам нужно что бы функция pop() забирала элементы с начала списка, для этого используем ее с аргументом ноль pop(0). Ниже приведен класс за основу которого был взят :
Функции списков:
append , extend — добавление;
insert — вставка;
index — найти индекс первого вхождения конкретного элемента;
count — подсчет повторов элемента;
remove , del — удаление элемента;
sort — сортировка;
reverse — реверс;
pop — извлечение элемента;
len — длина списка;
max — максимальный элемент;
min — минимальный элемент;
оператор in — проверка элемента на вхождение.
История о том, как однажды депривация сна смативировала айтишника к интересной движухе..
По образу своей деятельности, ночью Я обычно не сплю, а тут еще и на сессию приехал, днем экзамены.. И понесло меня читать в интернетах о том сколько можно не спать. Спустя некоторое время к движухе подключился приятель , утро доброе Миха Некоторое время вдвоем курили мануалы по теме на которую внегласно подписались, излогать все смысла не вижу, лучше выложу статьи достаточно полулярных авторов из не менее полулярного журнала: и . Без чтения статей было и так ясно, что нужно чем то заниматься, что бы не уснуть. Я в свою очередь решил поменять обои на рабочем столе, и пропал в поисках оных только для нетбука, параллельно мониторя состояние своего друга. Сайт с контентом был найден, но для просмотра и сохранения изображения нужно было пройти по ссылкам на три уровни ниже, мягко говоря это не комфортно. В столь нужный момент более менее интересная задача появилась, идея состояла в написании парсера и граббера картинок с сайта на языке Python. Но для начала ради интереса решил перейти в браузере в каталог с картинками, элементарно удалив имя изображения из URL (http://site.ru/wp-content/gallery/girls/), пару секунд ожидания и предо мной весь список изображений в этом каталоге.. Замечательно, задача упростилась на несколько порядков. Открыв Python Shell, импортируем пакет , и проверяем можем ли мы вообще получить список изображений по этому адресу.
>>> f = urllib.request.urlopen('http://site.ru/wp-content/gallery/girls/')
На выходе по сути должен быть html документ со списком имен файлов, не тут то было, время ожидания истекло, в питоне я еще не особо силен, делал по мануалам, переходим к запасному плану.. Качаем Wget под win, на сайте повеселили картинкой с недвусмысленным намеком. Я пользуюсь обоими системами. Пока качается Wget, смотрим по нему мануалы. После установки в Win7, Wget желательно сразу добавить в переменные среды PATH чтобы можно было одной командой его вызывать. Предвкушая победу набираем нужную команду, а именно "Скачать содержимое каталога http://site.ru/wp-content/gallery/girls/ и всех его подкаталогов, при этом не поднимаясь по иерархии каталогов выше: wget -r --no-parent http://site.ru/wp-content/gallery/girls/ наблюдая за занимательным процессом в командной строке и в папке как прибавляются картинки, чувствуем себя марком цукербергом когда он грабил картинки для своего фейс смеша тем же wget-ом в фильме "Социальная сеть".. Настоло время поделится полезностями:
С описанием червя можно ознакомиться на . У меня же с ним получилось познакомится спонтанно, решил подконектица к хабу и поснифить трафик, заодно поработать с wireshark. Минут через 15 моих эксперементов, на экране наблюдалось следующее:
Не будем углубляться в теорию, на тот момент самое главное было то, что нечто на компе с IP: 192.168.0.1 по средствам NBNS отсылает кучу запросов на широковещательный общий адрес сети(192.168.0.255), с которого пакеты расходятся по всем компьютерам. Сеть была свежей, машины новые, на всех из них был установлен дос, и ПО запускалось из под него, и только один с тем самым IP был с предустановленой WinXP. Без выхода в инет во всей сети, но непредусмотрительно оставленный с автозапуском на флешках, и действующими USB. Было очевидно откуда могло появится вредоносное ПО на компе, с еще не установленным антивирем.
Что бы оправдать свои догадки, вставил флешку, открыл консоль, перешел в нужный раздел и выполнил простую команду dir /A. На заранее чистом носителе, уже появился скрытый autorun.inf. Командой attrib -a -h -r -s autorun.inf этим мы снимаем все атрибуты с файла которые нам не дают его увидеть и прочесть. Лезть в свойства папки бессмысленно, так как вирь в памяти и все стандартные попытки будут обречены на провал. Открыв на редактирование авторан файл, оказалось что он зашифрован или забит специально мусором, среди которого и расположены команды на выполнение. Становится понятным что вирь распространяется на переносных носителях, значит и его тело которое запускается авторан файлом лежит где то рядом. А точнее в скрытой папке RECYCLER и далее в единственной подпапке с расширением *.vmx
Вспоминаем что нам надо вычеслить вредонос на целевой машине, форматируем флешку и дисконектим её. Запускаем на компе ProcessMonitor, включаем отслеживание изменений только в файловой системе. И настраиваем фильтр на создание и изменение файлов в путях которых содержаться строки autorun.inf и имя файла виря из папки RECYCLER с расширением .vmx Возвращаем флешку в USB и происходит следующее:
svchost.exe это процесс орининал, не подмененный и не запущенный из другой директории, при помощи SvchostAnalyzer просмотр библиотек процесса которые он подгружает ничего подозрительного не выявил. Пойти дальше у меня не хватало навыков, появилось предположение что всю деятельность прикрывает руткит. Ничего не остовалось, как только запустить AVZ с обновленными базами, просто на сканирование без всяких действий. По результатам оказалось что dll виря присутствовала в system32 и AVZ задетектил активность руткитов. В отчетах фигурировало название червя Kido. Когда полез глядеть на википедию, был удивлен, все о чем я рассказал совпадало с симптомами заражения. О использованном ПО расскажу в отдельных статьях.