;(function() { window.createMeasureObserver = (measureName) => { var markPrefix = `_uol-measure-${measureName}-${new Date().getTime()}`; performance.mark(`${markPrefix}-start`); return { end: function() { performance.mark(`${markPrefix}-end`); performance.measure(`uol-measure-${measureName}`, `${markPrefix}-start`, `${markPrefix}-end`); performance.clearMarks(`${markPrefix}-start`); performance.clearMarks(`${markPrefix}-end`); } } }; /** * Gerenciador de eventos */ window.gevent = { stack: [], RUN_ONCE: true, on: function(name, callback, once) { this.stack.push([name, callback, !!once]); }, emit: function(name, args) { for (var i = this.stack.length, item; i--;) { item = this.stack[i]; if (item[0] === name) { item[1](args); if (item[2]) { this.stack.splice(i, 1); } } } } }; var runningSearch = false; var hadAnEvent = true; var elementsToWatch = window.elementsToWatch = new Map(); var innerHeight = window.innerHeight; // timestamp da última rodada do requestAnimationFrame // É usado para limitar a procura por elementos visíveis. var lastAnimationTS = 0; // verifica se elemento está no viewport do usuário var isElementInViewport = function(el) { var rect = el.getBoundingClientRect(); var clientHeight = window.innerHeight || document.documentElement.clientHeight; // renderizando antes, evitando troca de conteúdo visível no chartbeat-related-content if(el.className.includes('related-content-front')) return true; // garante que usa ao mínimo 280px de margem para fazer o lazyload var margin = clientHeight + Math.max(280, clientHeight * 0.2); // se a base do componente está acima da altura da tela do usuário, está oculto if(rect.bottom < 0 && rect.bottom > margin * -1) { return false; } // se o topo do elemento está abaixo da altura da tela do usuário, está oculto if(rect.top > margin) { return false; } // se a posição do topo é negativa, verifica se a altura dele ainda // compensa o que já foi scrollado if(rect.top < 0 && rect.height + rect.top < 0) { return false; } return true; }; var asynxNextFreeTime = () => { return new Promise((resolve) => { if(window.requestIdleCallback) { window.requestIdleCallback(resolve, { timeout: 5000, }); } else { window.requestAnimationFrame(resolve); } }); }; var asyncValidateIfElIsInViewPort = function(promise, el) { return promise.then(() => { if(el) { if(isElementInViewport(el) == true) { const cb = elementsToWatch.get(el); // remove da lista para não ser disparado novamente elementsToWatch.delete(el); cb(); } } }).then(asynxNextFreeTime); }; // inicia o fluxo de procura de elementos procurados var look = function() { if(window.requestIdleCallback) { window.requestIdleCallback(findByVisibleElements, { timeout: 5000, }); } else { window.requestAnimationFrame(findByVisibleElements); } }; var findByVisibleElements = function(ts) { var elapsedSinceLast = ts - lastAnimationTS; // se não teve nenhum evento que possa alterar a página if(hadAnEvent == false) { return look(); } if(elementsToWatch.size == 0) { return look(); } if(runningSearch == true) { return look(); } // procura por elementos visíveis apenas 5x/seg if(elapsedSinceLast < 1000/5) { return look(); } // atualiza o último ts lastAnimationTS = ts; // reseta status de scroll para não entrar novamente aqui hadAnEvent = false; // indica que está rodando a procura por elementos no viewport runningSearch = true; const done = Array.from(elementsToWatch.keys()).reduce(asyncValidateIfElIsInViewPort, Promise.resolve()); // obtém todos os elementos que podem ter view contabilizados //elementsToWatch.forEach(function(cb, el) { // if(isElementInViewport(el) == true) { // // remove da lista para não ser disparado novamente // elementsToWatch.delete(el); // cb(el); // } //}); done.then(function() { runningSearch = false; }); // reinicia o fluxo de procura look(); }; /** * Quando o elemento `el` entrar no viewport (-20%), cb será disparado. */ window.lazyload = function(el, cb) { if(el.nodeType != Node.ELEMENT_NODE) { throw new Error("element parameter should be a Element Node"); } if(typeof cb !== 'function') { throw new Error("callback parameter should be a Function"); } elementsToWatch.set(el, cb); } var setEvent = function() { hadAnEvent = true; }; window.addEventListener('scroll', setEvent, { capture: true, ive: true }); window.addEventListener('click', setEvent, { ive: true }); window.addEventListener('resize', setEvent, { ive: true }); window.addEventListener('load', setEvent, { once: true, ive: true }); window.addEventListener('DOMContentLoaded', setEvent, { once: true, ive: true }); window.gevent.on('allJSLoadedAndCreated', setEvent, window.gevent.RUN_ONCE); // inicia a validação look(); })();
  • AssineUOL
Topo

Como enganaram o sensor de digital do Galaxy S10 usando uma taça de vinho

Sensor ultrassônico de digitais do S10 foi enganado. -
Sensor ultrassônico de digitais do S10 foi enganado.

Helton Simões Gomes

Do UOL, em São Paulo

06/04/2019 16h07

Resumo da notícia

  • Leitor ultrassônico de digitais é um dos trunfos do novo Galaxy S10
  • Ele usa um sistema complexo para reconhecer o dedo do dono do aparelho
  • Um internauta, porém, levou menos de 15 minutos para enganar o leitor
  • Tudo começou com uma taça de vinho e terminou com uma impressora 3D

Uma das grandes novidades do novo celular top de linha da Samsung, o Galaxy S10, é o leitor ultrassônico de impressões digitais, que fica embaixo da tela para reconhecer o dedo cadastrado.

A tecnologia por trás desse recurso é complexa, mas um internauta demorou menos de 15 minutos para criar uma maneira de enganar o sensor. E tudo começou com uma taça de vinho.

O autor do feito é um dono de um Galaxy S10, identificado apenas como "darkshark9" no fórum de discussões Reddit. Foi lá que ele descreveu o que ocorreu.

Primeiro, ele notou que uma impressão digital havia permanecido na superfície de uma taça de vinho. Tirou uma foto dela e editou a imagem no Photoshop para ressaltar as fissuras presentes nela. Depois, usou um software para converter a foto em um arquivo 3D. Por fim, usou uma impressora 3D para transformar o modelo digital em um objeto com relevo sobre uma tira de plástico transparente. Ele disse que todo o processo levou 13 minutos.

Mais seguro que seus antecessores, o sensor ultrassônico do Galaxy S10 envia ondas para o dedo posicionado sobre a tela. Quando elas retornam, ele é capaz de reconhecer com maior precisão se as ranhuras presentes naquela impressão digital são as mesmas do arquivo cadastrado em seus sistemas. Se as duas não baterem, nada feito: o celular não é destravado.

Foi para driblar essa peculiaridade do novo leitor de digitais do novo smartphone que o internauta usou a impressora 3D. Ele precisava de algo que reproduzisse aqueles espaçozinhos minúsculos que vemos na ponta dos nossos dedos. Como esse equipamento consegue criar objetos tridimensionais a partir de instruções digitais, foi a escolha perfeita.

Para fazer todo o truque funcionar, no entanto, faltava só mais uma coisa: ele teve que fazer uma pressãozinha enquanto posicionava sua digital falsa sobre o sensor de impressões do Galaxy S10. Isso quer dizer que simplesmente colocar o molde sobre a tela não teria efeito nenhum.

Como se sua descoberta já não fosse preocupante o suficiente, o internauta disse que não seria difícil para alguém com uma impressora 3D obter as digitais do dono de um celular roubado e imprimi-las para ter o ao telefone. Ainda mais porque impressões digitais ficam marcadas por todo corpo do smartphone.

Ele disse que fez tudo isso como um experimento para demonstrar que os leitores de digitais não são seguros. O UOL Tecnologia entrou em contato com a Samsung e atualizará este texto assim que a empresa sul-coreana responder.

Sensores biométricos foram introduzidos nos smartphones para substituir as senhas por algum traço físico do dono do aparelho. O objetivo é garantir que o celular seja desbloqueado apenas por seu dono. Esse princípio vale para os sensores de impressões digitais e para os de reconhecimento facial. Ainda que pretendam elevar o grau de privacidade dos telefones, não é a primeira vez que alguém consegue enganar um desses recursos e ter o ao que ele guarda.