SniperlCat 0.3.1, pasado a perl estricto y correjidos bugs varios
Esta versión no trae nada nuevo, así que va a ser corto. Se pasó todo el código a perl estricto (use strict), y se corriguieron fallos tontos al interpretar las opciones de la línea de comandos, por ejemplo, si se daemonizaba después de lanzar un hilo, el hilo se cerraba por que lo hacía el proceso original =P
El trigger no cambia (bueno, en realidad cambia el notify-send, que en vez de poner 0.3, es 0.3.1, pero es estético). El código_completo_está_en_github , aunque lo importante es el Sniperlcat.pl [o_en_plano]
ps: Ya me dirán por que * no dejarán usar break; en estricto !?
Usando proxies con Python
Presento un pequeño código para usar proxies SOCKS 4 y 5 en python, en principio la idea era mostrarlo junto un servidor proxy en C, pero viendo que con esto se podía tumbar, tardará un poco más...
El código es este (para descargar completo más abajo): from socket import socket, AF_INET, SOCK_STREAM, inet_aton, getaddrinfo,\
SOL_TCP
from string import letters
from random import choice
import sys
Lee siempre una cantidad de un socket
def sock_read(sock, n):
b = "" # Inicia el buffer
i = 0 # Tamaño del buffer
while (i < n): # Mientas no lee todo
c = sock.recv(n - i) # Lee lo que falta
if (len(c) < 1): # Si no se leyó nada
# es que el socket está cerrado
raise Exception("Closed socket")
b += c # Añadir lo nuevo al buffer
i += len(c) # y actualizar su tamaño
return b # Devolver el buffer
Convertir sockaddr a una dirección de red
def str2host(addr, ipv = 4):
for i in letters: # Si hay letras
if i in addr[0]: # es un nombre de dominio
d = getaddrinfo(addr[0], addr[1], 0, 0, SOL_TCP)
# La primera dirección, el
# primer dato de la última tupla
for j in d:
if (len(j[-1]) == 2) and (ipv == 4): # A ipv4 tuple
return inet_aton(j[-1][0])
elif (len(j[-1]) == 4) and (ipv == 6): # A ipv6 tuple
return inet_aton(j[-1][0])
raise Exception("Host not found")
# Sino se traduce directamente
return inet_aton(addr[0])
Pasa un número de 2 bytes a str
Suponiendo little endian
def uint16str(n):
data = [] # Prepara el buffer
data.append( chr(n & 255) ) # Lee el byte menos significativo
n >>= 8 # Mueve todo un byte a la derecha
data.append( chr(n & 255) ) # Lee el nuevo lsb
data.reverse() # Le da la vuelta (little endian)
return ''.join(data) # Y lo convierte en una cadeba
Envía el código de excepción de un servidor SOCKS4
def SOCKS4_ex(ans):
# Relación código/respuesta
s4_ex = { 91 : "Request rejected or failed",
92 : "Request rejected becasue SOCKS server cannot connect to
identd on the client",
93 : "Request rejected because the client program and identd
report different user-ids"}
raise Exception(s4_ex[ord(ans)]) # Produce la excepción
Envía el código de excepción de un servidor SOCKS5
def SOCKS5_ex(ans):
# Relación código/respuesta
s5_ex = { 1 : "General SOCKS server failure",
2 : "Connection not allowed by ruleset",
3 : "Network unreachable",
4 : "Host unreachable",
5 : "Connection refused",
6 : "TTL expired",
7 : "Command not supported",
8 : "Address type not supported" }
raise Exception(s5_ex[ord(ans)]) # Produce la excepción
Especifica la dirección a un proxy SOCKS
def SOCKS_hop(sock, addr, proto = 4, ipv = 4):
if (proto == 4): # Protocolo SOCKS4
# Mensaje de conexión
sock.send(chr(4) + chr(1) + uint16str(addr[1]) + str2host(addr) +\
chr(0))
# Mensaje de confirmación/error
code = sock_read(sock, 8)[1]
# Si algo falló
if (code != chr(90)):
# Mandar una excepción
SOCKS4_ex(code)
elif (proto == 5): # Protocolo SOCKS5
atype = None
if (ipv == 4): # Hosts ipv4
atype = chr(1)
elif (ipv == 6): # Hosts ipv6
atype = chr(4)
else:
raise Exception("Unknown IP version")
sock.send(chr(5) + chr(1) + chr(0))
# Mensaje de confirmación/error
code = sock_read(sock, 2)
if (code != (chr(5) + chr(0))):
raise Exception("Requiere autenticación")
# Mensaje de conexión
l = sock.send(chr(5) + chr(1) + chr(0) + atype + str(str2host(addr)) +\
uint16str(addr[1]))
# Mensaje de confirmación/error
code = sock_read(sock, l)[1]
# Si algo falló
if (code != chr(00)):
# Mandar una excepción
SOCKS5_ex(code)
else: # Protocolo desconocido
raise Exception("Unknown SOCKS version")
Simplemente hay que levantar una conexión hacia un proxy y luego llamar a
SOCKS_hopcon los siguientes argumentos:
* El socket que se uso para la conexión
* Una tupla dirección/puerto como al conectar un socket
* Versión de SOCKS: 4 o 5(Opcional, por defecto 4)
* Versión del protocolo IP (Opcional, por defecto 4)
*
Si se produce un error en el proceso (no está conectado a un servidor SOCKS o le servidor no se pudo conectar al nuevo host, por ejemplo) manda una excepción.
Para este ejemplo, si se pasa algún parámetro, se leerá como una lista de proxies (ip:puerto en cada línea) y va saltando entre proxies al azar. Sino se le pasa ningún parámetro se conecta a localhost en el puerto 1080 y intenta usarlo como servidor SOCKS5 para ver cuantas veces se puede conectar a si mismo [Cuidado]: unos cuantos hilos haciendo esto provocaron algo parecido a un DOS en un pequeño servidor SSH funcionando como proxy =P if name == "main":
if (len(sys.argv) > 1):
plist = []
f = open(sys.argv[1], "rt")
while True:
txt = f.readline()
if (len(txt) < 1):
break
addr = txt.split(":")
plist.append((addr[0], int(addr[1])))
f.close()
last = choice(plist) # Selecciona un proxy al azar
next = last
i = 0
sys.stdout.write("[" + str(i) + "] " + str(next))
sys.stdout.flush()
sock = socket(AF_INET, SOCK_STREAM)
sock.connect(next)
sys.stdout.write("\n")
while True:
i += 1
while (next == last):
next = choice(plist)
last = next
sys.stdout.write("[" + str(i) + "] " + str(next))
sys.stdout.flush()
SOCKS_hop(sock, next)
sys.stdout.write("\n")
else:
sock = socket(AF_INET, SOCK_STREAM)
#sock.connect(('127.0.0.1', 4444))
sock.connect(('localhost', 1080))
i = 0
while True:
#SOCKS_hop(sock, ('localhost', 4444))
SOCKS_hop(sock, ('127.0.0.1', 1080), 5)
i += 1
print i
El código completo [pysocks.py] [Referencias] SOCKS_4 SOCKS_4A RFC1928_-_SOCKS5
Proceso de escritura de un shellcode
Hoy me ha entrado del vicio de escribir un shellcode, aquí queda el proceso para quien se pregunte como se escriben estos extraños seres de la fauna binaria.
Actualización: me había olvidado del BITS 32 en el shellcode para que funcione bien
Un shellcode, llamados así porque generalmente lo que hacían era presentar una shell (aunque se puede hacer cualquier cosa con ellos), son trozos de código ensamblador, normalmente pasados a formato hexadecimal para un "consumo" más cómodo, cuya característica más importante es que se pueden cargar en cualquier posición de memoria.
Empezamos escribiendo un código que llame a execl con /bin/bash como parámetro[ http://pastebin.com/8FTgE4yz ]:
===============================================================================
section .data ; Datos comando: db '/bin/bash', 0 nullstring: dd 0
section .text ; Código global _start
_start: ; Inicio mov eax, 11 ; execve mov ebx, comando ; path del ejecutable mov ecx, nullstring ; un 0, no se usarán parámetros
int 0x80 ; Joeeeeeeeee!!! una de kerneeeeeeeel !!!
_end: ; Esto solo lo finaliza mov eax, 1 ; sys_exit mov ebx, 0
int 0x80
===============================================================================
Lo siguiente es eliminar las direcciones absolutas lo que incluye todo el section .data, así que usaremos el stack para eso, recordar que crece hacia abajo, hay que meter las cosas "al revés"
===============================================================================
section .text ; Código global _start
_start: ; Inicio push dword 0
mov ecx, esp ; Se guarda esta posición del stack ; servirá para los argumentes
; //bin/bash , para cuadrarlo en words push dword 0x68736162 ; hsab (bash) push dword 0x2f6e6962 ; /nib (bin/) push word 0x2f2f ; //
mov eax, 11 ; execve mov ebx, esp ; path del ejecutable int 0x80 ; Se llama al kernel
_end: ; Esto solo lo finaliza mov eax, 1 ; sys_exit mov ebx, 0 int 0x80
===============================================================================
Queda eliminar los 0's del código, ya que desensamblado es así
===============================================================================
00000000 680000 push word 0x0 00000003 0000 add [bx+si],al 00000005 89E1 mov cx,sp 00000007 686261 push word 0x6162 0000000A 7368 jnc 0x74 0000000C 686269 push word 0x6962 0000000F 6E outsb 00000010 2F das 00000011 66682F2FB80B push dword 0xbb82f2f 00000017 0000 add [bx+si],al 00000019 0089E3CD add [bx+di- 0x321d],cl 0000001D 80B8010000 cmp byte [bx+si+0x1],0x0 00000022 00BB0000 add [bp+di+0x0],bh 00000026 0000 add [bx+si],al 00000028 CD80 int 0x80
===============================================================================
Y un shellcode con bytes nulos no es todo lo útil que podría, aquí los XOR allanan el camino
===============================================================================
BITS 32
section .text ; Código global _start
_start: ; Inicio xor eax, eax
push eax
mov ecx, esp ; Se guarda esta posición del stack ; servirá para los argumentes
; ////bin/bash , para cuadrarlo en words push dword 0x68736162 ; hsab (bash) push dword 0x2f6e6962 ; /nib (bin/)
push word 0x2f2f ; //
mov al, 11 ; execve
mov ebx, esp ; path del ejecutable
int 0x80
_end: ; Esto solo lo finaliza xor eax, eax ; sys_exit xor ebx, ebx
inc eax int 0x80
===============================================================================
Desensamblado:
===============================================================================
00000000 31C0 xor ax,ax 00000002 50 push ax 00000003 89E1 mov cx,sp 00000005 686261 push word 0x6162 00000008 7368 jnc 0x72 0000000A 686269 push word 0x6962 0000000D 6E outsb 0000000E 2F das 0000000F 66682F2FB00B push dword 0xbb02f2f 00000015 89E3 mov bx,sp 00000017 CD80 int 0x80 00000019 31C0 xor ax,ax 0000001B 31DB xor bx,bx 0000001D 40 inc ax 0000001E CD80 int 0x80
===============================================================================
Sin ningún NULO, listo para servir
===============================================================================
\x31\xc0\x50\x89\xe1\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x66\x68\x2f\x2f\xb0\x0b\x89\xe3\xcd\x80\x31\xc0\x31\xdb\x40\xcd\x80
===============================================================================
ps: para quién llegó hasta aquí hay premio xD, un script para pasar el dumpeo binario de un shellcode al formato de string que se suele utilizar [ http://pastebin.com/mubdwfXS ]
Que aproveche :D!
Intérprete de Redcode
[Link corregido]
Hoy traigo un pequeño intérprete de Redcode (si, el lenguaje del Corewars). Tiene sus limitaciónes (digamos que sigue las primeras versiones del lenguaje), por ejemplo, no tiene p-space ni modificadores (instrucción.Modificador) a excepcion de STS, que muestra un carácter por pantalla, y LDS que obtiene un carácter de STDIN (instrucciones que no se usan en el juego ), para más referencias [ Redcode_-_Esolang ].
Obviamente la idea al programar esto fue intentar comprender un poco más como funcionan los intérpretes y compiladores.
Centrandose en el programa en sí, (se puede descargar aquí [redcode01.tar.gz]), lo único que hay que hacer es make para compilarlo, y
===============================================================================
./redcode
===============================================================================
para intérpretar un código.Además decir que ignora las líneas con un '#' al principio, para permitir que el intérprete se lance con un #!.
Hay más formas de usarlo, se pueden ver con
===============================================================================
kenkeiras@viaxante:~/%%%%%$ ./redcode
Uso: ./redcode [--help |--compile | --decompile | --load-compiled] [--verbose]
[--mem-length=
===============================================================================
Creo que es bastante auto explicativo.
La parte de compilar y cargar directamente despues está para evitar el procesamiento extra del parser (esto para Redcode no tiene mucho sentido, pero para otros lenguajes podria tenerlo,y recordemos que la idea era aprender =) ).
Por último, algunos programas utilizados para probarlo...
ps: Perdón desde ya por el surfing de punteros :S.
El hola mundo (no puede faltar :D) [http://pastebin.com/cbtGkj5F]:
===============================================================================
; Redcode Hello World, John Metcalf
write sts.a hello, 0 sts.b }write, 0 djn write, #7
hello dat 72, 101 ; He dat 108, 108 ; ll dat 111, 44 ; o, dat 32, 87 ; W dat 111, 114 ; or dat 108, 100 ; ld dat 33, 10 ; !\n
===============================================================================
Adaptado para usar SPL (varios procesos)[http://pastebin.com/rqrugthE]:
===============================================================================
; Redcode multiprocess Hello World ; Original by John Metcalf ; Modified by kenkeiras (Added parallel functions)
spl fork write sts.a hello, 0 djn -1, #7
hello dat 72, 101 ; He dat 108, 108 ; ll dat 111, 44 ; o, dat 32, 87 ; W dat 111, 114 ; or dat 108, 100 ; ld dat 33, 10 ; !\n
fork sts.b }write, 0 djn -1, #7
===============================================================================
Un imp (simple pero eficaz para probar los extremos de la memoria):
===============================================================================
mov 0, 1
===============================================================================
Y uno que se copia seguido hacia atras[http://pastebin.com/x8qNf15b]:
===============================================================================
;name Backrunner ;author Kenkeiras
SUB #7,inst ;Para reajustar el puntero de instruccion SUB #6,pos ; " MOV >inst,>pos SEQ inst,check JMP -2
JMP -14 ;Al proximo paso
pos DAT #-9 inst DAT #0 ;Los valores que quedaran despues de copiarse a si mismos check DAT #2
===============================================================================
Hasta otra.
[Referencias] http://impomatic.blogspot.com/ Redcode_-_Esolang
Probando scratch
"Scratch es un lenguaje de programación que hace fácil crear tus
propias historias interactivas, animaciones, juegos, musica y arte -
- y compartir tus creaciones en la red.
Cuando la gente joven crea y comparte proyectos de Scratch, aprenden
importantes ideas sobre las matemáticas y la computación, mientras
aprenden también a pensar de forma creativa, razonar
systematicamente y trabajar colaborativamente."
Eso es lo que dicen de este proyecto en_su_web, solo cabría añadir que fue desarrollado en el MIT y que el código está basado en "bloques" de instrucciones, no en texto, haciendolo muy visual y evitando errores sintácticos.
Obviamente no es un lenguaje pensado para la programación en general aunque permita muchas cosas de ella: variables, condiciones, bucles, operaciones... La interfaz es bastante simple y autoexplicativa, tanto que para programar solo hace falta saber leer, hasta los bloques de código están traducidos a varios idiomas: [http://videobin.org/+2bu/2me.html]
El programa se puede descargar de aquí http://info.scratch.mit.edu/ Scratch_1.4_Download , los que usen una distro con apt-get pueden añadir directamente el repositorio
===============================================================================
deb http://ppa.launchpad.net/scratch/ppa/ubuntu
===============================================================================
La versión de la distro debería ser la más "equivalente" posible a la versión de ubuntu (para Trisquel Taranis, por ejemplo, sería lucid)
Algo que me parecio curioso es que soporta gráficos de tortuga, como el lenguaje logo, por ejemplo, este 'código':
Genera esta figura:
También permite interactuar fácilmente con el usuario, por ejemplo, este utiliza el lápiz de los gráficos de tortuga para 'perseguir' al ratón:
Como se puede ver, el lenguaje es muy intuitivo y no hay que andar por medio internet buscando como hacer tal o cual cosa, el propio programa provee los bloques con las instrucciones, solo hay que moverlos hasta donde se quieran poner y listo :D.
Eso es todo, nos vemos.
Un autómata celular para generar números pseudo-aleatorios
La idea no es la primera vez que se oye, creo que fue_Wolfram_quién_lo_propuso en_su_momento, pero el concepto no deja de ser curioso, y el otro día trasteando con Golly me encontre con que una pequeña variante del juego_de_la vida_de_Conway, con la diferencia de que una "célula" también puede "nacer" si tiene 4 vecinos (y no solo 3) llamado "3-4 life", que hace que patrones sencillos crezcan indefinidamente quedando el contenido en su interior algo aleatorio, esta es una simulación de las 250 primeras generaciones [http:// videobin.org/+2be/2ly.html].
Lo que intenta hacer el código es expandir la figura inicial estas 250 generaciones e introducir una "semilla de aleatoriedad", que puede ser un string cualquiera o se puede leer de un archivo, lo que hará que la figura crezca de forma distinta cada vez. Se deja además 1000 generaciones para que esta semilla se mezcle bien, y el resultado se utiliza para generar números pseudo-aleatorios, que no creo que sean criptográficamente.
Una peculiaridad es que el campo es de 40x40 (pero esto se puede cambiar) y toroidal, es decir, cuando la primera fila comprueba lo que tendría encima, se leen las de la última, y vieceversa, lo mismo pasa con derecha e izquierda.
El código está aquí [autorand.tar.gz], solo hay que compilar autorand.c directamente.
Por defecto la "semilla de aleatoriedad" se lee desde el teclado, esto se puede cambiar al lanzar el comando:
===============================================================================
./autorand [-fs
===============================================================================
Eso es todo por hoy, mañana más... y dificilmente peor =D
SniperlCat 0.3, suma y sigue
Pues nada, nueva versión de sniperlcat, los cambios son: - Los avisos los hace un script a parte, eliminando GTK de las dependencias y haciendo que no haya que trastear en el código para que haga algo distinto con los avisos. - Corregido al bug que lo volvia paranoico al cerrar el dispositivo...al final solo había que reabrirlo =) - Añadida la opción de poner a la escucha un puerto cualquiera para detectar los scanners que se conectan a el, si se utiliza varias veces se escuchan varios puertos (cada uno en un hilo distinto).
La opción de escuchar puertos se añadió por la necesidad de detectar scanners de conexión, (y de evitar tener que ser root para detectar los escaneos), que además se pueda elegir el mensaje que envía es para hacerse pasar por un servicio legítimo, por ejemplo, "SSH-2.0-OpenSSH_5.3p1 Debian- 3ubuntu4" hace que amap lo marque como un servidor openssh =D
Los cambios están subidos a github [http://github.com/kenkeiras/Sniperlcat], también se pueden descargar los dos archivos por separado [sniperlcat.pl] y [trigger.sh].
La sintaxis del comando queda así, entonces (todo es retrocompatible)
===============================================================================
Sniperlcat 0.3
sniperlcat [-h]|[-d | -v ] [-nf] [-c] [-n
===============================================================================
Eso es todo, hasta otra.
Invertir los canales de sonido
Otro script más que engrosa las listas de lo programado solo por programar [http://pastebin.com/FzQmDxKP].
Recibe como parámetros el archivo original y el nombre del que se creará y copia el sonido del primero en el segundo cambiando el canal de la derecha por el de la izquierda y viceversa.
Meh... pues si que quedo pequeño el post =P.
Como generar una onda de Audio para archivos WAV (PCM)
Como en su momento no encontré nada sobre este tema, aquí va una pequeña explicación de como generar audio modulado en PCM, lo que usa por ejemplo, el formato WAV.
Partiremos de algunos conceptos básicos que supongo que conoceréis:
Sobre las ondas de sonido:
* Frecuencia de la onda: veces en un segundo que la onda se repite (o que
pasa por el valor intermedio).
* Amplitud de la onda: en este caso, la distancia entre el punto más alto
y el más bajo, determinará el volumen.
*
Sobre su representación en el archivo:
* Framerate: número de veces por segundo que se representa la onda (a más
framerate, más cercano es a la onda original y mejor calidad).
* Canales: número de salidas del audio (1: Mono, 2: Stereo).
*
* Ancho de canal: bits que se dedican a cada frame de cada canal (suele ser
de 16 bits).
*
Para la manipulación de los archivos WAV se puede usar la librería_estándar de_python_wave, haciendo que el manejo del archivo sea muy simple, por lo que me centraré en la generación de la onda, que es lo que no implementa.
Supongamos, por ejemplo, que queremos generar una onda de 300Hz que dure 1 segundo, lo primero es generar una onda completa que nos servirá de base:
- Si la frecuencia es cero, la onda es plana, así que se representaría como un solo valor, 0
Sino, tendremos para generar una onda completa, para ello se necesitan tantos frames como framerate/frecuencia, para que la onda esté completa, además, como la onda es sinusoidal, tomará valores de seno de entre 0 y 2 PI , así que por último hay que partir de la base b = (2 * pi) / frames y multiplicarlo por cada frame, el código de esta parte quedaría así:
import math
def getBase(freq, framerate):
# Si no es una onda plana
if (freq != 0):
base = []
# Se obtiene el numero de frames a generar
frames = int(framerate / abs(freq))
# Y la base de los valores que tomaran
p = (math.pi * 2) / frames
# Por ultimo se genera la onda sinusoidal entre seno de 0 y 2*Pi
for i in xrange(frames):
base.append(math.sin(i * p))
# Si es una onda plana
else:
base = [0]
return base
El siguiente paso es añadir a la onda base el volumen y los canales, para añadir el volumen simplemente hay que multiplicar el valor de un frame por el volumen, el valor del volumen (usando PCM con signo, como en WAV) puede variar entre 0 y 2**(ancho de banda - 1) - 1, para 8 bits sería entre 0 y 127, y para 16 bits, entre 0 y 32767. Por ultimo, solo hay que repetir el frame por cada canal (aunque si va a ser la misma onda no hay motivos para usar múltiples canales...)
Fija el volumen y los canales
def setVolChan(src, vol, n_can):
out = []
for i in src:
n = int(i * vol) # Se aplica el volumen
out.append([n] * n_can) # Y se replica para otros canales
return out
A continuación hay que extender la onda para todo el tiempo que cubra
Extiende la base a todo el tiempo
def mkFrames(base, t, framerate):
base_flen = len(base) / float(framerate) # Lo que dura la base
n = int(round(t / base_flen)) # Las veces que hay que repetirla
return base * n
Y solo queda convertir la onda a una cadena (es el formato que utiliza la librería wave), si los canales fueran de 8 bits se podría usar una funcion de array directamente:
cadena = array.array('b', original).tostring()
Sino, hay que hacerlo a mano
def arr2Stream(sample, width):
stream = ""
for i in sample: # Por cada frame
for k in i: # Y cada canal
for j in xrange(width):
stream += chr(k & 255 ) # Se extrae un byte
k >>= 8
return stream
Un código completo sería (los cambios se hacen en las variables al principio del codigo), entonces [audio_sample.py]:
!/usr/bin/env python
canales = 2 # Stereo
framerate = 11025
ancho = 16
volumen = 10000 # Para un ancho de canal de 16 bits
frecuencia = 300 # Hz
duracion = 2 # Segundos
archivo = "salida.wav"
def arr2Stream(sample, width):
stream = ""
for i in sample: # Por cada frame
for k in i: # Y cada canal
for j in xrange(width):
stream += chr(k & 255 ) # Se extrae un byte
k >>= 8
return stream
def getBase(freq, framerate):
# Si no es una onda plana
if (freq != 0):
base = []
# Se obtiene el numero de frames a generar
frames = int(framerate / abs(freq))
# Y la base de los valores que tomaran
p = (math.pi * 2) / frames
# Por ultimo se genera la onda sinusoidal entre seno de 0 y 2*Pi
for i in xrange(frames):
base.append(math.sin(i * p))
# Si es una onda plana
else:
base = [0]
return base
Fija el volumen y los canales
def setVolChan(src, vol, n_can):
out = []
for i in src:
n = int(i * vol) # Se aplica el volumen
out.append([n] * n_can) # Y se replica para otros canales
return out
Extiende la base a todo el tiempo
def mkFrames(base, t, framerate):
base_flen = len(base) / float(framerate) # Lo que dura la base
n = int(round(t / base_flen)) # Las veces que hay que repetirla
return base * n
def genFrames(freq, t, framerate, vol, chan, width):
s = getBase(freq, framerate)
s = setVolChan(s, vol, chan)
s = mkFrames( s, t, framerate)
return arr2Stream(s, width)
import math, wave
w = wave.open(archivo, "wb")
w.setnchannels(canales)
w.setsampwidth(ancho / 8)
w.setframerate(framerate)
w.writeframes(genFrames(frecuencia, duracion, framerate, volumen, canales, ancho / 8))
w.close()
Ve con root =)
[Offtopic] Thunderbird te avisa si te olvidas de adjuntar algo
Parece que thunderbird añadió la característica de avisar al usuario de que falta algo por adjuntar si observa algo en el mensaje que indica que se debería haber hecho (algo como nombrar un tipo de archivo común)
[http://1.bp.blogspot.com/_26RJWnubh-w/TMboUfMRFrI/AAAAAAAAARk/YaUd_xhHL0o/ s320/thunder.png] [Recordatorio de Adjunto] ¿Te olvidaste de añadir un adjunto? [X ¡Oh, me olvide!] [✓ No, enviar ahora]
Btw, si a alguién le falla el programa para capturar la pantalla puede probar con: =============================================================================== sleep 1;import -frame salida.png ===============================================================================
Se puede cambiar el 1 de sleep por el tiempo que se esperará antes de sacar la foto, y salida.png por el nombre del archivo de salida, solo hay que lanzarlo y cuando el cursor cambie, hacer click sobre la ventana que se quiere capturar. Se puede eliminar el -frame para no capturar la barra superior de la ventana.
Saludos